Discussion:
builtin: Is Lexical Export Idempotent?
(too old to reply)
Paul "LeoNerd" Evans
2024-01-25 18:30:58 UTC
Permalink
TL;DR: If you `use builtin ...` multiple times in a row, do they count?
Or are they idempotent? This matters when you `no builtin ...` again.

-----

The `builtin` module performs exports lexically, not symbolically. This
means it inserts named functions in the lexical scope of its `use`
import, rather than just into the calling package. This is good for a
variety of reasons. E.g.

use builtin 'true';

We then added unimport, which removes them again, which is handy for a
few cornercases, and in particular useful if you want to remove *one*
awkward name from the overall version bundle, if you e.g. `use v5.40`.

use v5.40;
no builtin 'blessed';

All's good so far.

The implementation of hiding things in the pad again (the newly-added
"TOMBSTONE" flag) isn't currently very good, as it hides the names too
well. For example, most people would agree that combined, the two lines
like

use builtin 'true';
no builtin 'true';

should in effect do nothing, and in particular if a prior `true()`
function had been lexically visible, it should now remain so.

So, I've been working on a branch to make the implementation better. I
now have things like this working fine:

my sub true() { return "yes" }
use builtin 'true';
no builtin 'true';
is(true(), "yes");


But now I have hit a snag. There's a question around what it means to
import the same name multiple times in a row. For example:

use builtin 'true';
use builtin 'true';

What does this even mean? Has it been imported twice, or just once?

At this point, what would a single unimport operation do? Does it hide
both of the imports, or just one? What would people expect the
following to do?

my sub true() { return "yes" }
use builtin 'true';
use builtin 'true';
no builtin 'true';
say "TRUE is now " . true();

Does it print "yes", or "1"?
--
Paul "LeoNerd" Evans

***@leonerd.org.uk | https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/ | https://www.tindie.com/stores/leonerd/
Paul "LeoNerd" Evans
2024-01-25 20:14:51 UTC
Permalink
On Thu, 25 Jan 2024 20:35:11 +0100
Post by Paul "LeoNerd" Evans
TL;DR: If you `use builtin ...` multiple times in a row, do they
count? Or are they idempotent? This matters when you `no builtin
...` again.
No counting. Idempotence only. Final Destination.
Only ZUUL.
use strict 'refs';
use strict 'refs';
no strict 'refs';
# strict refs should be off here
use warnings 'syntax';
use warnings 'syntax';
no warnings 'syntax';
# I don't want syntax warnings here
That's what I'd expect, at least.
Righty. That makes sense I suppose.

In that case, since the version-bundle import has to check for symbols
the caller already has, I can just reuse that same logic here and
simplify the import time a bit.

That at least temporarily avoids the question earlier posed, so that's
good :)
--
Paul "LeoNerd" Evans

***@leonerd.org.uk | https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/ | https://www.tindie.com/stores/leonerd/
p***@tux.freedom.nl
2024-01-26 07:48:02 UTC
Permalink
Post by Paul "LeoNerd" Evans
TL;DR: If you `use builtin ...` multiple times in a row, do they count?
Or are they idempotent? This matters when you `no builtin ...` again.
No counting. Idempotence only. Final Destination.
use strict 'refs';
use strict 'refs';
no strict 'refs';
# strict refs should be off here
use warnings 'syntax';
use warnings 'syntax';
no warnings 'syntax';
# I don't want syntax warnings here
That's what I'd expect, at least.
Me too
+n
--
H.Merijn Brand https://tux.nl Perl Monger http://amsterdam.pm.org/
using perl5.00307 .. 5.37 porting perl5 on HP-UX, AIX, and Linux
https://tux.nl/email.html http://qa.perl.org https://www.test-smoke.org
Paul "LeoNerd" Evans
2024-01-26 17:28:56 UTC
Permalink
On Thu, 25 Jan 2024 18:30:58 +0000
Post by Paul "LeoNerd" Evans
TL;DR: If you `use builtin ...` multiple times in a row, do they
count? Or are they idempotent? This matters when you `no builtin ...`
again.
Thanks all for the many replies; universally everyone thinks it should
be idempotent and shouldn't count per call. This all seems reasonable,
and fits in well with other models.

To that end then, I have implemented some extra code and added some
more tests. Review comments welcome:

https://github.com/Perl/perl5/pull/21887

As a general reminder: I know not everyone will want to or be able to
review the C-level implementation parts, but if at least everyone who's
expressed an opinion on how it should behave could check that the
additional tests added here match up with their expectations of the
behaviour and comment as such on the PR, that'd be really handy.
--
Paul "LeoNerd" Evans

***@leonerd.org.uk | https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/ | https://www.tindie.com/stores/leonerd/
Loading...