PSC #034 2021-08-20
A special single-subject meeting to look into the "namespaces" question
which has been lurking. We invited a few extra people who have
expressed thoughts in that direction:
Present: Karl Williamson, Nicholas Clark, Paul Evans, Ricardo Signes,
Yves Orton
We began by revisiting the original questions that had led us to this
point. These were mostly concerns about how to add new functions to the
Perl language that had come up in the discussions about adding `trim`
and a few other places. It has been previously observed that using
feature bits via the `use feature` pragma are fine enough for genuinely
new syntax features such as control-flow syntax, but they are not a
good fit for adding things that look and behave like "regular"
functions.
We all generally agreed here - some other mechanism should exist, and
if it had existed at the time when such features as `fc` were added
then no doubt we would have used that, rather than the way they have
been.
Having established this as the overall theme of the discussion, we
moved to focus on what should be provided instead and how it should
behave. We felt it would be nice to be:
* A polyfill - i.e. use some familiar syntax like
"use SomeModule qw( some function names );" so that a dual-life
module can be made and put on CPAN, allowing older perls to make
use of it.
* Lexical - much like `use strict`, `use feature`, etc.. rather than
any of the "inject subs into caller's package" ideas like Exporter.
Once these points we made, we observed that we still hadn't actually
answered a question of what namespaces should actually be provided. Or
even whether it was necessary to provide more than one at all. Various
previous email discussions had hinted at thoughts like "string" and
"ref" and "math" and "net" and so on, but so far we haven't really seen
a case to suggest needing more than one. If instead we say we'll just
take a single namespace, then that removes concerns like having to
decide which space everything lives in. It also adds a bit of "don't
add too much" pressure, and keeps minds focused on ensuring everything
has a unique name, thus avoiding such questions like "what if we wanted
both string::length and array::length?". If there's only one space of
names then there would need to be a fairly high bar to entry, as to
what we consider for inclusion. We don't want to create a thousand new
built-in functions that are all trivial variations on things that can
be done with existing Perl syntax and/or regular modules in core or on
CPAN. The space should be for things that are outright impossible in
pureperl (e.g. Scalar::Util::weaken()), or things that are
prohibitively expensive or complex to implement in that manner.
Since there didn't seem to be a case for adding multiple names we
proceeded on the basis of having just one. While we hadn't settled on a
name (see "outstanding questions" below), we had to pick something for
discussion purposes, so we settled on "builtin". It isn't ideal (see
below) but it serves for now.
The basic thought was roughly that new perls going forward would just
have a bunch of functions always available by a fully-qualified name,
such as `builtin::reftype`, that could be called immediately without
having to "use" anything; e.g. as
#!perl
print "The type of array refs is ", builtin::reftype([]), "\n";
or
$ perl -E 'say "The type of arrayrefs is ", builtin::reftype([])'
There would exist some module - perhaps of the same name - such that
you can (lexically) import these as short names:
#!perl
use builtin 'reftype';
print "The type of array refs is ", reftype([]), "\n";
It being a lexical import means it acts much like "use feature" et.al,
rather than package imports which cause namespace-pollution issues for
things like object classes. This was felt to be a useful property,
outweighing the "it is different to e.g. use Scalar::Util " feeling. In
any case it's an all-lowercase pragmatic module, it's allowed to feel
different.
Since we're looking at just one actual "namespace" for normal
functions, we wondered if actually the existing CORE::GLOBAL::
mechanism would already be sufficient for this. It turns out not really
- you can't add new names to it, only override existing ones, so it
wouldn't work as a polyfill mechanism on older perls.
For publishing a polyfill module, there were thoughts on how it should
be version-numbered, and whether the syntax ought to *mandate* that you
include a version number in the `use` statement. E.g. it's often a good
idea to `use List::Util v1.29 'pairs'` so if the List::Util module is
too old you get a nicer error message. But should we mandate this for
the functions module?
Next came the question of what actual functions to provide in this
mechanism. It seemed fairly noncontroversial that such things as
Scalar::Util::reftype() and ::blessed() would be available. There also
seems to be a case for things like POSIX::ceil() and ::floor(), which
seem good to have in the core language and not need to pull in the
giant POSIX.so just for that. The discussion continued into listing
more places where such things could be found - such as Internals::,
UNIVERSAL.c - but it seems we can consider these on a casewise basis,
once the initial mechanism is inplace and the overall shape seems like
a good one.
As time was nearly up, we decided there seemed a good enough place to
begin wrapping up. We were in fairly good agreement that a mechanism
needs to be created, and roughly what shape it should have. There
became evident a bunch of more specific questions about it, that seems
a good place to finish on as these are good candidates for further
discussion:
* What is the actual name for the fully-qualified namespace used by
these new functions? We used "builtin" during the discussion, but if
you have to `use` a module to get at them they can hardly be said to
be built-in
* What is the name of the shim-loader pragma module used to obtain the
shortname lexical aliases? It could match the function namespace,
but it doesn't have to. Other candidates include "function" or
"functions". Though they bear a visual similarity to the "feature"
module, which we are trying to avoid. Maybe there are some other
words to be found.
* What functions to actually include in this new namespace? We already
have quite a few candidates for places to look for existing ideas,
which should be sufficient to try out the mechanism before we think
about adding actually-new ones:
+ `Scalar::Util`
+ Existing features like `fc`
+ UNIVERSAL.c
+ The badly-named `Internals::`
+ Commonly-used POSIX functions like `ceil()`
+ Rarely-used POSIXisms in core perl like `gethostbyname`
* Should it interact with `use VERSION`? Since we're already in a
world where `use VERSION` implies strict + warnings + a feature
bundle, it would be easy enough to suggest that it also pulls in a
function bundle of the same version. It would be nice if you could
#!perl
use v5.40;
say "The reftype of arrays is ", reftype [];
--
Paul "LeoNerd" Evans
leonerd@leonerd.org.uk | https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/ | https://www.tindie.com/stores/leonerd/
A special single-subject meeting to look into the "namespaces" question
which has been lurking. We invited a few extra people who have
expressed thoughts in that direction:
Present: Karl Williamson, Nicholas Clark, Paul Evans, Ricardo Signes,
Yves Orton
We began by revisiting the original questions that had led us to this
point. These were mostly concerns about how to add new functions to the
Perl language that had come up in the discussions about adding `trim`
and a few other places. It has been previously observed that using
feature bits via the `use feature` pragma are fine enough for genuinely
new syntax features such as control-flow syntax, but they are not a
good fit for adding things that look and behave like "regular"
functions.
We all generally agreed here - some other mechanism should exist, and
if it had existed at the time when such features as `fc` were added
then no doubt we would have used that, rather than the way they have
been.
Having established this as the overall theme of the discussion, we
moved to focus on what should be provided instead and how it should
behave. We felt it would be nice to be:
* A polyfill - i.e. use some familiar syntax like
"use SomeModule qw( some function names );" so that a dual-life
module can be made and put on CPAN, allowing older perls to make
use of it.
* Lexical - much like `use strict`, `use feature`, etc.. rather than
any of the "inject subs into caller's package" ideas like Exporter.
Once these points we made, we observed that we still hadn't actually
answered a question of what namespaces should actually be provided. Or
even whether it was necessary to provide more than one at all. Various
previous email discussions had hinted at thoughts like "string" and
"ref" and "math" and "net" and so on, but so far we haven't really seen
a case to suggest needing more than one. If instead we say we'll just
take a single namespace, then that removes concerns like having to
decide which space everything lives in. It also adds a bit of "don't
add too much" pressure, and keeps minds focused on ensuring everything
has a unique name, thus avoiding such questions like "what if we wanted
both string::length and array::length?". If there's only one space of
names then there would need to be a fairly high bar to entry, as to
what we consider for inclusion. We don't want to create a thousand new
built-in functions that are all trivial variations on things that can
be done with existing Perl syntax and/or regular modules in core or on
CPAN. The space should be for things that are outright impossible in
pureperl (e.g. Scalar::Util::weaken()), or things that are
prohibitively expensive or complex to implement in that manner.
Since there didn't seem to be a case for adding multiple names we
proceeded on the basis of having just one. While we hadn't settled on a
name (see "outstanding questions" below), we had to pick something for
discussion purposes, so we settled on "builtin". It isn't ideal (see
below) but it serves for now.
The basic thought was roughly that new perls going forward would just
have a bunch of functions always available by a fully-qualified name,
such as `builtin::reftype`, that could be called immediately without
having to "use" anything; e.g. as
#!perl
print "The type of array refs is ", builtin::reftype([]), "\n";
or
$ perl -E 'say "The type of arrayrefs is ", builtin::reftype([])'
There would exist some module - perhaps of the same name - such that
you can (lexically) import these as short names:
#!perl
use builtin 'reftype';
print "The type of array refs is ", reftype([]), "\n";
It being a lexical import means it acts much like "use feature" et.al,
rather than package imports which cause namespace-pollution issues for
things like object classes. This was felt to be a useful property,
outweighing the "it is different to e.g. use Scalar::Util " feeling. In
any case it's an all-lowercase pragmatic module, it's allowed to feel
different.
Since we're looking at just one actual "namespace" for normal
functions, we wondered if actually the existing CORE::GLOBAL::
mechanism would already be sufficient for this. It turns out not really
- you can't add new names to it, only override existing ones, so it
wouldn't work as a polyfill mechanism on older perls.
For publishing a polyfill module, there were thoughts on how it should
be version-numbered, and whether the syntax ought to *mandate* that you
include a version number in the `use` statement. E.g. it's often a good
idea to `use List::Util v1.29 'pairs'` so if the List::Util module is
too old you get a nicer error message. But should we mandate this for
the functions module?
Next came the question of what actual functions to provide in this
mechanism. It seemed fairly noncontroversial that such things as
Scalar::Util::reftype() and ::blessed() would be available. There also
seems to be a case for things like POSIX::ceil() and ::floor(), which
seem good to have in the core language and not need to pull in the
giant POSIX.so just for that. The discussion continued into listing
more places where such things could be found - such as Internals::,
UNIVERSAL.c - but it seems we can consider these on a casewise basis,
once the initial mechanism is inplace and the overall shape seems like
a good one.
As time was nearly up, we decided there seemed a good enough place to
begin wrapping up. We were in fairly good agreement that a mechanism
needs to be created, and roughly what shape it should have. There
became evident a bunch of more specific questions about it, that seems
a good place to finish on as these are good candidates for further
discussion:
* What is the actual name for the fully-qualified namespace used by
these new functions? We used "builtin" during the discussion, but if
you have to `use` a module to get at them they can hardly be said to
be built-in
* What is the name of the shim-loader pragma module used to obtain the
shortname lexical aliases? It could match the function namespace,
but it doesn't have to. Other candidates include "function" or
"functions". Though they bear a visual similarity to the "feature"
module, which we are trying to avoid. Maybe there are some other
words to be found.
* What functions to actually include in this new namespace? We already
have quite a few candidates for places to look for existing ideas,
which should be sufficient to try out the mechanism before we think
about adding actually-new ones:
+ `Scalar::Util`
+ Existing features like `fc`
+ UNIVERSAL.c
+ The badly-named `Internals::`
+ Commonly-used POSIX functions like `ceil()`
+ Rarely-used POSIXisms in core perl like `gethostbyname`
* Should it interact with `use VERSION`? Since we're already in a
world where `use VERSION` implies strict + warnings + a feature
bundle, it would be easy enough to suggest that it also pulls in a
function bundle of the same version. It would be nice if you could
#!perl
use v5.40;
say "The reftype of arrays is ", reftype [];
--
Paul "LeoNerd" Evans
leonerd@leonerd.org.uk | https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/ | https://www.tindie.com/stores/leonerd/