develooper Front page | perl.perl5.porters | Postings from May 2021

Re: Namespaces (was Re: Revisiting trim)

Thread Previous | Thread Next
May 28, 2021 09:27
Re: Namespaces (was Re: Revisiting trim)
Message ID:
On Thu, 27 May 2021 at 19:20, Neil Bowers <> wrote:
> Hi Yves,
> But I really really appeal to those in charge these days to addressthis issue of where new functional (not control) keywords go and howit can be done in a forwards and backwards compatible way (meaning usefeature is out).
> We’ve added this to the agenda for this week’s meeting, under "namespaces".
> That will start the ball rolling, and is an opportunity for people to share any well-formed thoughts on this matter.

I would like to separate my thoughts into two categories.

The first concerns the namespaces themselves. On this subject I dont
have a strong opinion, I lean towards "scalar" over "string", but I
know the internals and newbies don't and overall I don't actually care
too much provided the namespaces are well thought out and somewhat
"coherent".  Eg, for me "scalar", "array", "hash", "reference", "list"
etc are a consistent and cohesive definition, if somewhat arbitrary
and maybe coarse grained. "string" sounds ok, but what do you do for
numbers, some numeric things maybe should be in "math", others in
"num" maybe? And then you have functions oriented towards operating on
perl primitives and its type system, Eg you could argue that the
entire Ref::Util should be built in, as should the entire Scalar::Util
and List::Util, so where would you put them. We have prior art with
'utf8', 're'. Anyway, to me I think you could argue about the perfect
set of namespaces, and ultimately this is a "perfect is the enemy of
good enough" case, nearly any sane categorization would probably be
fine. Just keep the outliers in mind, eg, where should utf8::downgrade
go in the new scheme if it werent where it is? Where would the 're'
special functions go? (regexp_pattern) What about the functions for
locking hashes that live in Hash::Util, arguably they should be built
in too, what namespace would/should they go into?  For me the main
point is here is that we agree "no more unnecessary new changes to the
default language, new functions must go into a namespace if they can",
the exact namespaces chosen is less important to me provide it

The second category is how they are added to the language. I care
about this a lot more than the namespaces we use. I don't think we
should use the as currently implemented "feature" mechanism for these
keywords, and I think we should think carefully about choosing
implementations that cannot be provided in a transparently backwards
compatible way. What I would like is that we can somehow say:

    use keyword "string::trimmed" => "trimmed"; # it would be nice if
we could use "as" instead of "=>" here, but it wouldnt be back-compat

and have keyword do the magic of determining if we are on a perl that
contains string::trimmed and exports it as "trimmed", and if we are
not, it loads the module which "supplies" string::trimmed (and which
is responsible installing trimmed into the "string" namespace), and
then does the require export.

If someone does

   use keyword "string::trimmed";

it simply ensures that string::trimmed is available, eg no import into
the current namespace.

On a perl new enough where they *knew* it had "string:trimmed" they
could write perl -e'print string::trimmed(...)' just like they
currently can for anything defined in universal.c

The purpose of the "keyword" pragma would be to declare that you need
a given built in to be there, and to provide a way that we can provide
back-compat machinery that can fake it up so that things work all the
way back to 5.6 if we wanted.

This would not render "feature" obsolete, changes to the control
structures of perl, new operators for instance as opposed to
functions, or new control structures would be triggered by feature.

I believe that the perl docs have specified that single word lower
case pragamatta names are reserved for Perl internals use. Adding a
new "keyword" pragma and the required logic to do this would be pretty
straightforward, for most of us on this list I imagine it would take
us less time to code it up than it would to reply to this mail. :-)

With this I feel we would be backwards and forwards compatible. Any
time we added a new keyword function like trimmed() we could implement
its backcompat as well, and that backwards compat layer would work as
far back as we wish.

Done nicely we could have the "keyword" pragmatta produce nice errors like this:

"this version of 'keyword' does not recognize "string::trimmed",
either there is no such keyword or you should upgrade your version of
the 'keyword' module."
"you need to install Perl::Keyword::string::trimmed to supply the
"string::trimmed" keyword for this version of perl"

If the keyword module is a dual lifed module, then we can have our
cake and eat it too. By using segregated namespaces we dont pollute
main::, we can make functions available in one liners by fully
qualified function call syntaxt, we have a clean way to declare and
request the keywords we want, and how we want to address them in our
namespace, and we have a clean way to write plug ins for back compat.
Done right this would make it easy to deal with dependencies in a
distribution, you could simply declare the list of Perl::Keyword::
modules you depend on, and it would Just Work on all versions.

NOTE: an observation, if we want to supply seamless back-compat then
we should eschew implementation choices that cant be implemented in a
backwards compatible way. For instance in the trimmed() proposal to
provide an efficient inline modification the patch is using compiler
optimizations to determine the target is the same as the argument, if
I am correct that this is not something you can do in an XS module
alone then we should think carefully. Code that is optimized on a
modern perl might end up quadratic on an older one. In such a case it
might be better to make the inplace (and optimal trim strategy) case
occur in void context alone. This is obviously debatable, you could
argue we do "best effort back compat" and that we should be able to
implement the back compat shims as pure perl modules.  So long as the
policy is clear and consistent it doesnt matter I guess. I lean
towards maximum back-compat.

My point here is perl already has a more or less usable mechanism for
adding new functions to language, namespaces, and it has all the
machinery needed to add new ones to the core in modern perls and still
provide a shim layer that makes them available in older perls. The
"use feature" api is bound to perl version, and doesnt provide any
machinery for adding back-compat shims. It also doesnt have existing
logic for mapping functions in one namespace into another. I think a
new way to manage these new functions would make a lot of the issues
and acrimony about them go away. a clean and clear rule:

"new functions are added to the perl core via the 'keyword' frame,
which means population into the appropriate reserved namespace, and
providing a back compat layer for keyword, and patches to the module itself, and releasing that as a dual life module".

My $0.02


perl -Mre=debug -e "/just|another|perl|hacker/"

Thread Previous | Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About