Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[perl #113930] Lexical subs

39 views
Skip to first unread message

Father Chrysostomos

unread,
Jul 1, 2012, 5:23:26 PM7/1/12
to bugs-bi...@rt.perl.org
# New Ticket Created by Father Chrysostomos
# Please include the string: [perl #113930]
# in the subject line of all future correspondence about this issue.
# <URL: https://rt.perl.org:443/rt3/Ticket/Display.html?id=113930 >


There doesn’t appear to be a ticket for this already, so I’m making one. There is also another reason: I think I know how to make it work.

The last time this came up, the two main issues were:

1)

If ‘my sub’ follows the same scoping rules as existing my and sub declarations, then the lexical sub will not be visible inside itself, unless declared beforehand. But if ‘my’ creates a new pad entry, then this won’t work:

my sub foo;
my sub foo { ... }

because the second one creates a new pad entry and does not modify the existing one.

2)

Should declarations be compile-time or run-time? If they are compile-time declarations, then how does one redefine a sub (c.f. problem 1); and how does a lexical sub close over variables? If it is a run-time thing, then it is radically different from ‘sub foo {...}’, so shouldn’t it look different?

These questions can be summarized as: When does a lexical closure close over outer variables? What else has to happen to make it work?

----------------------------------------------------------------------

I think the solution to #1 is to make ‘sub foo { ... }’ respect a lexical declaration that precedes it. Just as $x = 3 does not assign to the package variable $x after a my $x declaration, so ‘sub foo { ... }’ should not create a package sub after ‘my sub foo;’.

That in itself pretty much resolves #2, but we have (at least) two variants:

• Lexical subs close over variables when the name comes into scope (which could happen multiple times with loops).
• Lexical subs close over variables when referenced or called.
• Lexical subs close over variables when *first* referenced or called.

For the most part, there is no observable difference here, until it comes to referential identity and for loops.

I don’t think we have to worry about referential identity, since optimisations would make all three variants nearly identical in that regard.

For for loops we have to decide what this will do:

for my $x (1..10) {
my sub foo { push @results, $x }
foo();
}

The @results will be 1..10, 1..10 and (1)x10, respectively for the three variants.

And what about this?

my sub foo;
for my $x (1..10) {
sub foo { push @results, $x }
foo();
}

Results: (undef)x10, 1..10, (1)x10

And this would produce the same:

my $x;
my sub foo { push @results, $x }
for $x (1..10) {
foo();
}

In all these cases, the second variant seems more intuitive, at least to me. In fact, that’s similar to how format closures work. This prints the numbers from 1 to 10:

my $x;
format =
@<<<<<<
$x
.
for $x (1..10) {
write;
}

If we introduce lexical aliases via \my $x = $y, we will need to figure this out for the sake of that, too.

-----------------------------------------------------------

Next issue: What should state sub do? Should it behave the same way as my sub? Should it close over the variables the first time through the function? Should it be an error (currently it is not) until we decide?

I think it should be just a named package sub (‘Variable will not stay shared’ and all), but visible only in a lexical scope.

-----------------------------------------------------------

I think it is pretty obvious that our sub should create a lexical alias to a package sub, so that this will work:

sub foo { warn "main" }
package bar;
foo(); # calls main::foo

-----------------------------------------------------------

‘my format’ and ‘my package’ would be going a bit too far. :-)

Father Chrysostomos via RT

unread,
Jul 1, 2012, 5:49:56 PM7/1/12
to perl5-...@perl.org
On Sun Jul 01 14:23:26 2012, sprout wrote:
> Next issue: What should state sub do? Should it behave the same way
> as my sub? Should it close over the variables the first time
> through the function? Should it be an error (currently it is not)
> until we decide?
>
> I think it should be just a named package sub (‘Variable will not stay
> shared’ and all), but visible only in a lexical scope.

s/just/just like/


--

Father Chrysostomos

Kent Fredric

unread,
Jul 1, 2012, 7:13:56 PM7/1/12
to perl5-...@perl.org, bugs-bi...@rt.perl.org
On 2 July 2012 09:23, Father Chrysostomos <perlbug-...@perl.org> wrote:
>
> for my $x (1..10) {
> my sub foo { push @results, $x }
> foo();
> }
>
> The @results will be 1..10, 1..10 and (1)x10, respectively for the three variants.

As far as what I expect would happen, I'd imagine, if I saw that code,
that it would do the same as:

for my $x (1..10) {
my $foo = sub { push @results, $x }
$foo();
}


> And what about this?
>
> my sub foo;
> for my $x (1..10) {
> sub foo { push @results, $x }
> foo();
> }
>

If I saw that, I'd expect the same as:

my $foo = sub {};
for my $x (1..10) {
$foo = sub { push @results, $x };
$foo();
}

In both case, my brain sees "my sub foo" and thinks its just sugar for
"my $foo = sub "



However, if you were to use 'state foo' , the expectation I'd have is :

for my $x (1..10) {
state sub foo { push @results, $x }
foo();
}

would be the same as:

my $foo;
for my $x (1..10) {
$foo //= sub { push @results, $x }
$foo();
}

That being, @results would be (1)x10 ( Though, slightly unintuitive I feel )

I think people who are doing that though are doing it to be
"optimised" somehow, and would expect the behaviour of:

my $foo;
my $x;
for $x (1..10) {
$foo //= sub { push @results, $x }
$foo();
}


--
Kent

perl -e "print substr( \"edrgmaM SPA NOcomil.ic\\@tfrken\", \$_ * 3,
3 ) for ( 9,8,0,7,1,6,5,4,3,2 );"

Father Chrysostomos via RT

unread,
Jul 5, 2012, 5:46:38 PM7/5/12
to perl5-...@perl.org
newMYSUB is listed in the API. (It has an A in embed.fnc and shows up
in the undocumented list in perlapi.pod.)

This is its signature:

#ifdef PERL_MAD
OP *
#else
void
#endif
Perl_newMYSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)

Implementing lexical subs within the constrains of the current
parameters and return value is not impossible, but hardly sane. It
would be easier to make newMYSUB a stub that dies, and create a
completely new function.

Instead, can I just change this? Nothing uses it. All it does
currently is die anyway.

--

Father Chrysostomos

Eric Brine

unread,
Jul 5, 2012, 6:11:28 PM7/5/12
to perlbug...@perl.org, perl5-...@perl.org

I'm particularly interested in the ability of "use Module;" to create a lexical sub in the using scope. I looked at C<< newMYSUB >>, but I ended up using Lexical::Sub for Syntax::Feature::QwComments and ::Loop. So if your new interface makes that easy, I like it :D

- Eric

Father Chrysostomos via RT

unread,
Jul 5, 2012, 6:59:30 PM7/5/12
to perl5-...@perl.org, ike...@adaelis.com
If you already have a compiled CV, it might be possible using
PAD_SETSV(pad_add_name_pv("&foo", 0, 0, 0), cv). Currently in bleadperl
you can do that (untested), but ‘foo’ in the source code won’t look it up.

My changes should make ‘foo’ generate a padcv op (nonexistent in blead)
in that case.

newMYSUB is probably not what you want, as it is analogous to newSUB:
It takes PL_compcv and stuffs it in the slot indicated by the second
argument, attaching the passed-in op tree, and popping the stack back to
what it was before start_subparse() (assuming you passed the return
value of start_subparse() as the first argument to newSUB).

--

Father Chrysostomos

Jesse Luehrs

unread,
Jul 5, 2012, 11:30:53 PM7/5/12
to Father Chrysostomos via RT, perl5-...@perl.org
If all it does is die, clearly nobody can be using this for any real
purpose. I'd say go ahead and change it.

-doy

Eric Brine

unread,
Jul 5, 2012, 11:55:54 PM7/5/12
to perlbug...@perl.org, perl5-...@perl.org
On Thu, Jul 5, 2012 at 6:59 PM, Father Chrysostomos via RT <perlbug...@perl.org> wrote:
> I'm particularly interested in the ability of "use Module;" to create a
> lexical sub in the using scope. I looked at C<< newMYSUB >>, but I
ended up
> using Lexical::Sub for Syntax::Feature::QwComments and ::Loop. So if your
> new interface makes that easy, I like it :D

If you already have a compiled CV, it might be possible using
PAD_SETSV(pad_add_name_pv("&foo", 0, 0, 0), cv).  Currently in bleadperl
you can do that (untested), but ‘foo’ in the source code won’t look it up.

No, I did not have an already compiled CV. I needed a stub to pass to cv_set_call_parser and cv_set_call_checker In fact, I found I just needed to *declare* the sub, so I ended up simply using

CV* const qwcv = get_cvn_flags("Syntax::Feature::QwComments::replacement_qw", 43, GV_ADD);

If you already have a compiled CV, it might be possible using
PAD_SETSV(pad_add_name_pv("&foo", 0, 0, 0), cv).  Currently in bleadperl
you can do that (untested), but ‘foo’ in the source code won’t look it up.

Are you planning on having Perl look there?
 
- Eric

Father Chrysostomos via RT

unread,
Jul 6, 2012, 12:38:04 AM7/6/12
to perl5-...@perl.org, ike...@adaelis.com
On Thu Jul 05 20:56:18 2012, ike...@adaelis.com wrote:
> On Thu, Jul 5, 2012 at 6:59 PM, Father Chrysostomos via RT <
> perlbug...@perl.org> wrote:
>
> > > I'm particularly interested in the ability of "use Module;" to
> create a
> > > lexical sub in the using scope. I looked at C<< newMYSUB >>, but I
> > ended up
> > > using Lexical::Sub for Syntax::Feature::QwComments and ::Loop. So
> if your
> > > new interface makes that easy, I like it :D
> >
> > If you already have a compiled CV, it might be possible using
> > PAD_SETSV(pad_add_name_pv("&foo", 0, 0, 0), cv).
>
> No, I did not have an already compiled CV. I needed a stub to pass to
> cv_set_call_parser and cv_set_call_checker In fact, I found I just
> needed
> to *declare* the sub, so I ended up simply using
>
> CV* const qwcv =
> get_cvn_flags("Syntax::Feature::QwComments::replacement_qw", 43,
> GV_ADD);

I misspoke. I meant ‘your own CV’, as opposed to PL_compcv.

> > Currently in bleadperl
> > you can do that (untested), but ‘foo’ in the source code won’t look
> it up.
> >
>
> Are you planning on having Perl look there?

Yes. On the sprout/lexsub branch it already does, but only works for
our subs.

--

Father Chrysostomos

Father Chrysostomos via RT

unread,
Jul 7, 2012, 2:35:49 PM7/7/12
to perl5-...@perl.org
On Sun Jul 01 14:23:26 2012, sprout wrote:
> ...[W]e have (at least) two
> variants:
>
> • Lexical subs close over variables when the name comes into scope
> (which could happen multiple times with loops).
> • Lexical subs close over variables when referenced or called.
> • Lexical subs close over variables when *first* referenced or called.
>
> For the most part, there is no observable difference here, until it
> comes to referential identity and for loops.
>
> I don’t think we have to worry about referential identity, since
> optimisations would make all three variants nearly identical in
> that regard.

Actually we do.

State variables are not persistent across anonymous subroutines.

push @subs, sub { state $x } for 1..10;

will give you ten subroutines, each with a different $x.

I find that to be completely counterintuitive. (It is also completely
undocumented.) It means that ‘state $x’ might only create one variable,
or might create more than one, depending on what type of sub it is
defined in.

It also creates yet another set of scoping rules for people to remember.
Flip-flops are shared between clones, so why not state variables?

The problem it raises for lexical subs is that it is not at all clear
when my sub foo { state $x } will create a new $x.

If state variables were intended to replace this sort of thing:

{
my $x;
sub fooer {
sub { ++$x; foo($x); }
}
}

then they have failed to do so.

Is this something we can fix, or will it break too many things?

--

Father Chrysostomos

Father Chrysostomos via RT

unread,
Jul 7, 2012, 2:57:59 PM7/7/12
to perl5-...@perl.org
In fact, they have been this way since they were added in commit
952306aca1, at least for closures. The code that causes state vars to
be created anew was not touched by that patch, so it seems like an
oversight. Other anonymous subs started recreating state vars in commit
a74073ad, sixteen months later, which I think was for consistency’s sake.

...

And I just found this message, which shows that it was very deliberate:

http://www.nntp.perl.org/group/perl.perl5.porters/;msgid=20070906085...@iabyn.com

So now I’m stuck on how to implement my sub foo { state $x }.

--

Father Chrysostomos

Tom Christiansen

unread,
Jul 7, 2012, 3:52:57 PM7/7/12
to perlbug...@perl.org, perl5-...@perl.org
"Father Chrysostomos via RT" <perlbug...@perl.org> wrote
on Sat, 07 Jul 2012 11:35:49 PDT:

> On Sun Jul 01 14:23:26 2012, sprout wrote:
>> ...[W]e have (at least) two
>> variants:
>>
>> • Lexical subs close over variables when the name comes into scope
>> (which could happen multiple times with loops).
>> • Lexical subs close over variables when referenced or called.
>> • Lexical subs close over variables when *first* referenced or called.
>>
>> For the most part, there is no observable difference here, until it
>> comes to referential identity and for loops.
>>
>> I don’t think we have to worry about referential identity, since
>> optimisations would make all three variants nearly identical in
>> that regard.

> Actually we do.

> State variables are not persistent across anonymous subroutines.

> push @subs, sub { state $x } for 1..10;

> will give you ten subroutines, each with a different $x.

> I find that to be completely counterintuitive. (It is also completely
> undocumented.)

Not so. Camel v4, chapter 7, page 324:

Finally, when we say that a state variable is initialized only once, we don’t mean
to imply that state variables in separate closures are the same variables. They
aren’t, so each gets its own initialization. This is how state variables differ from
static variables in other languages.

Larry was quite certain about that part, because he wanted to make sure
people understood how it worked, and that it did so by deliberate intent:
each closure is meant to get *its own* copy of a state variable.

> It means that ‘state $x’ might only create one variable, or might
> create more than one, depending on what type of sub it is defined in.

True.

> It also creates yet another set of scoping rules for people to remember.
> Flip-flops are shared between clones, so why not state variables?

Because it was designed to work this way.

> The problem it raises for lexical subs is that it is not at all clear
> when my sub foo { state $x } will create a new $x.

If we view C<my sub> as a declaration, than I cannot see why there
would ever be more than one of them, and therefore, more than one $x.

Are you worried about this situation?

sub outer {
my @subs;
for $i (1 .. 10) {
my sub inner {
state $x = rand();
return [ $i => $x ];
}
push @subs, \&inner;
}
return @subs;
}

The important question here is whether all those $x variables have
the same random number, or whether they have different ones.

And no, I don't know what the right answer is. I do agree that
is the right question, though. :)

> If state variables were intended to replace this sort of thing:

> {
> my $x;
> sub fooer {
> sub { ++$x; foo($x); }
> }
> }

> then they have failed to do so.

I don't believe they were.

> Is this something we can fix, or will it break too many things?

I'm not sure "fix" is the operative term here, considering that
it would certainly break existing code.

my @subs;
for my $decade (0 .. 10) {
push @subs, sub {
state $counter = 10 * $decade;
return $counter++ % 10;
};
}

There's also the argument that breaking this changes the
designed intent of state. And the documentation.

Can't see a good argument for all that.

Nonetheless, I can see your conundrum. I don't suppose you
have a current rakudo/perl6 and could check out how/whether
it works there? S04 has this:

http://perlcabal.org/syn/S04.html

There is a new state declarator that introduces a lexically scoped
variable like my does, but with a lifetime that persists for the life
of the closure, so that it keeps its value from the end of one call to
the beginning of the next. Separate clones of the closure get separate
state variables. However, recursive calls to the same clone use the
same state variable.

And later on:

The semantics of INIT and START are not equivalent to each other in the
case of cloned closures. An INIT only runs once for all copies of a cloned
closure. A START runs separately for each clone, so separate clones can
keep separate state variables:

our $i = 0;
...
$func = { state $x will start { $x = $i++ }; dostuff($i) };

But state automatically applies "start" semantics to any initializer, so this also works:

$func = { state $x = $i++; dostuff($i) }

Each subsequent clone gets an initial state that is one higher than the
previous, and each clone maintains its own state of $x, because that's
what state variables do.

And later on there is this, which is interesting but not completely
revealing, since it deals with a my not a state:

Lexical names do not share this problem, since the symbol goes out of
scope synchronously with its usage. Unlike global subs, they do not need a
compile-time binding, but like global subs, they perform a binding to the
lexical symbol at clone time (again, conceptually at the entry to the
outer lexical scope, but possibly deferred.)

sub foo {
# conceptual cloning happens to both blocks below
my $x = 1;
my sub bar { print $x } # already conceptually cloned, but can be lazily deferred
my &baz := { bar(); print $x }; # block is cloned immediately, forcing cloning of bar
my $code = &bar; # this would also force bar to be cloned
return &baz;
}

There may also be applicable points in S06, since you can my subs
in perl6, and in fact, the default is my sub not our sub:

http://perlcabal.org/syn/S06.html#Named_subroutines

Hm, have you thought about our sub? I think it is the same in perl6
as regular perl5 subs are — that is, ones interred in the package symbol
table — but I might be wrong.

--tom

Father Chrysostomos via RT

unread,
Jul 7, 2012, 4:23:17 PM7/7/12
to perl5-...@perl.org, tch...@perl.com
Thank you.

Could you write a patch to perlsub then? :-)

What it currently says is terribly vague. In fact, I would go so far as
to say that it doesn’t even state that ‘state’ creates persistent
variables. It begins by saying that ‘state’ can be used instead of ‘my’
to declare a variable, and then goes straight into examples. Examples
are supposed to supplement, not supplant, descriptions.
I think I have the right answer now. If we document that only
*anonymous* subroutines get their own copies of state variables when
cloned, then my subs (personal subs? idiotic subs?) share them.

In the example you gave, those $x variables would all have the same
random number.

If whether \&inner will clone the sub or not is supposed to be a matter
of optimisation, that’s the only way it can work.

> There's also the argument that breaking this changes the
> designed intent of state. And the documentation.

Maybe the Camel, but certainly not perlsub. :-)

> And later on there is this, which is interesting but not completely
> revealing, since it deals with a my not a state:
>
> Lexical names do not share this problem, since the symbol goes out
> of
> scope synchronously with its usage. Unlike global subs, they do
> not need a
> compile-time binding, but like global subs, they perform a binding
> to the
> lexical symbol at clone time (again, conceptually at the entry to
> the
> outer lexical scope, but possibly deferred.)
>
> sub foo {
> # conceptual cloning happens to both blocks below
> my $x = 1;
> my sub bar { print $x } # already conceptually
> cloned, but can be lazily deferred
> my &baz := { bar(); print $x }; # block is cloned
> immediately, forcing cloning of bar
> my $code = &bar; # this would also force
> bar to be cloned
> return &baz;
> }

That is interesting, since it is very similar to what I came up with on
my own.

If a sub is conceptually cloned when the block enters, does that mean
that my $code = &bar (\&bar in p5) twice in a row should produce the
same value?

How does Perl 6 deal with my subs in for loops?


>
> There may also be applicable points in S06, since you can my subs
> in perl6, and in fact, the default is my sub not our sub:
>
> http://perlcabal.org/syn/S06.html#Named_subroutines
>
> Hm, have you thought about our sub?

I’ve already implemented it. :-) See the sprout/lexsub branch.

It is analogous to our $var, in that the declaration persists across
package declarations.

$ ./perl -Ilib -e 'our sub foo { warn 42 } package bar; foo()'
42 at -e line 1.

$ ./perl -Ilib -MO=Concise -e 'package a; our sub foo { warn 42 }
package bar; foo()'
6 <@> leave[1 ref] vKP/REFC ->(end)
1 <0> enter ->2
2 <;> nextstate(bar 3 -e:1) v:{ ->3
5 <1> entersub[t2] vKS/TARG ->6
- <1> ex-list K ->5
3 <0> pushmark s ->4
- <1> ex-rv2cv sK ->-
4 <$> gv(*a::foo) s ->5
-e syntax OK

> I think it is the same in perl6
> as regular perl5 subs are — that is, ones interred in the package
> symbol
> table — but I might be wrong.

Whether it is or no, I wot not. I have not followed Perl 6 developement
closely at all. If it is different in Perl 6, I do not advocate
adopting ‘our sub’ from Perl 6, since ‘our’ already works a certain way
in Perl 5, so ‘our sub’ should follow that.

--

Father Chrysostomos

Father Chrysostomos via RT

unread,
Jul 7, 2012, 8:44:46 PM7/7/12
to perl5-...@perl.org, tch...@perl.com, perl6-l...@perl.org
I’m forwarding this to the Perl 6 language list, so see if I can find an
answer there.

[This conversation is about how lexical subs should be implemented in
Perl 5. What Perl 6 does may help in determining how to iron out the
edge cases.]

On Sat Jul 07 13:23:17 2012, sprout wrote:
> On Sat Jul 07 12:53:32 2012, tom christiansen wrote:
> > Are you worried about this situation?
> >
> > sub outer {
> > my @subs;
> > for $i (1 .. 10) {
> > my sub inner {
> > state $x = rand();
> > return [ $i => $x ];
> > }
> > push @subs, \&inner;
> > }
> > return @subs;
> > }
> >
> > The important question here is whether all those $x variables have
> > the same random number, or whether they have different ones.
> >
> > And no, I don't know what the right answer is. I do agree that
> > is the right question, though. :)
>
> I think I have the right answer now. If we document that only
> *anonymous* subroutines get their own copies of state variables when
> cloned, then my subs (personal subs? idiotic subs?) share them.
>
> In the example you gave, those $x variables would all have the same
> random number.
>
> If whether \&inner will clone the sub or not is supposed to be a matter
> of optimisation, that’s the only way it can work.
...
This question might be more appropriate: In this example, which @a does
the bar subroutine see (in Perl 6)?

sub foo {
my @a = (1,2,3);
my sub bar { say @a };
@a := [4,5,6];
bar();
}

--

Father Chrysostomos

Tom Christiansen

unread,
Jul 7, 2012, 9:34:27 PM7/7/12
to perlbug...@perl.org, perl5-...@perl.org, perl6-l...@perl.org
"Father Chrysostomos via RT" <perlbug...@perl.org> wrote
on Sat, 07 Jul 2012 17:44:46 PDT:

> I’m forwarding this to the Perl 6 language list, so see if I can find
> an answer there.

I do have an answer from Damian, which I will enclose below, and a
Rakudo result for you.

> [This conversation is about how lexical subs should be implemented in
> Perl 5. What Perl 6 does may help in determining how to iron out the
> edge cases.]

[...]

> This question might be more appropriate: In this example, which @a
> does the bar subroutine see (in Perl 6)?

> sub foo {
> my @a = (1,2,3);
> my sub bar { say @a };
> @a := [4,5,6];
> bar();
> }

The answer to your immediate question is that if you call foo(),
it prints out 456 under Rakudo.

Following is Damian's answer to my question, shared with permission.

--tom

From: Damian Conway <dam...@conway.org>
To: Tom Christiansen <tch...@perl.com>
CC: Larry Wall <la...@wall.org>
Date: Sun, 08 Jul 2012 07:17:19 +1000
Delivery-Date: Sat, 07 Jul 2012 15:19:09
Subject: Re: my subs and state vars
In-Reply-To: <22255.1341691089@chthon>

X-Spam-Status: No, score=-102.6 required=4.5 tests=BAYES_00,RCVD_IN_DNSWL_LOW,
USER_IN_WHITELIST autolearn=ham version=3.3.0

X-Google-Sender-Auth: UHLwfgo2kyvv2prdl6qJm-RfLF8
Content-Type: text/plain; charset=ISO-8859-1

> It looks like perl5 may be close to having my subs, but a puzzle
> has emerged about how in some circumstances to treat state
> variables within those. [I'm pretty sure that perl6 has thought
> this through thoroughly, but [I] am personally unfamiliar with the
> outcome of said contemplations.]
>
> I bet you aren't, though. Any ideas or clues?

The right things to do (and what Rakudo actually does) is to treat
lexical subs as lexically scoped *instances* of the specified sub
within the current surrounding block.

That is: a lexical sub is like a "my" var, in that you get a new one
each time the surrounding block is executed. Rather than like an "our"
variable, where you get a new lexically scoped alias to the same package
scoped variable.

By that reasoning, state vars inside a my sub must belong to each
instance of the sub, just as state vars inside anonymous subs belong to
each instance of the anonymous sub.

Another way of thinking about what Perl 6 does is that:

my sub foo { whatever() }

is just syntactic sugar for:

my &foo := sub { whatever() }

That is: create a lexically scoped Code object and alias it at run-time
to an anonymous subroutine. So the rules for state variables inside
lexical subs *must* be the same as the rules for state variables inside
anonymous subs, since they're actually just two ways of creating the
same thing.

With this approach, in Perl 6 it's easy to specify exactly what you want:

sub recount_from ($n) {

my sub counter {
state $count = $n; # Each instance of &counter has its own count
say $count--;
die if $count == 0;
}

while prompt "recount $n> " {
counter;
}
}

vs:

sub first_count_down_from ($n) {

state $count = $n; # All instances of &counter share a common count

my sub counter {
say $count--;
die if $count == 0;
}

while prompt "first count $n> " {
counter;
}
}

Feel free to forward the above to anyone who might find it useful.

Damian

Father Chrysostomos via RT

unread,
Jul 7, 2012, 9:54:15 PM7/7/12
to perl5-...@perl.org, perl6-l...@perl.org, dam...@conway.org, tch...@perl.com
On Sat Jul 07 18:35:03 2012, tom christiansen wrote:
> "Father Chrysostomos via RT" <perlbug...@perl.org> wrote
> on Sat, 07 Jul 2012 17:44:46 PDT:
>
> > I’m forwarding this to the Perl 6 language list, so see if I can
> find
> > an answer there.
>
> I do have an answer from Damian, which I will enclose below, and a
> Rakudo result for you.
>
> > [This conversation is about how lexical subs should be implemented
> in
> > Perl 5. What Perl 6 does may help in determining how to iron out
> the
> > edge cases.]
>
> [...]
>
> > This question might be more appropriate: In this example, which @a
> > does the bar subroutine see (in Perl 6)?
>
> > sub foo {
> > my @a = (1,2,3);
> > my sub bar { say @a };
> > @a := [4,5,6];
> > bar();
> > }
>
> The answer to your immediate question is that if you call foo(),
> it prints out 456 under Rakudo.

Thank you. So the bar sub seems to be closing over the name @a (the
container/variable slot/pad entry/whatever), rather than the actual
array itself.

Since I don’t have it installed, could you tell me what this does?

sub foo {
my @a = (1,2,3);
my sub bar { say @a };
bar();
@a := [4,5,6];
bar();
}
foo();

And this?

sub foo {
my @a = (1,2,3);
bar();
@a := [4,5,6];
bar();
my sub bar { say @a };
}
foo();

And this?

sub foo {
my @a = (1,2,3);
my sub bar { say @a };
my $bar = &bar;
$bar(); # is this syntax right?
@a := [4,5,6];
$bar();
}
foo();
Does that mean I cannot call it before it is declared?

> That is: create a lexically scoped Code object and alias it at
> run-time
> to an anonymous subroutine. So the rules for state variables
> inside
> lexical subs *must* be the same as the rules for state variables
> inside
> anonymous subs, since they're actually just two ways of creating
> the
> same thing.

I see.

>
> With this approach, in Perl 6 it's easy to specify exactly what
> you want:
>
> sub recount_from ($n) {
>
> my sub counter {
> state $count = $n; # Each instance of &counter has
> its own count
> say $count--;
> die if $count == 0;
> }
>
> while prompt "recount $n> " {
> counter;
> }
> }
>
> vs:
>
> sub first_count_down_from ($n) {
>
> state $count = $n; # All instances of &counter share
> a common count
>
> my sub counter {
> say $count--;
> die if $count == 0;
> }
>
> while prompt "first count $n> " {
> counter;
> }
> }
>
> Feel free to forward the above to anyone who might find it useful.

What I am really trying to find out is when the subroutine is actually
cloned, and whether there can be multiple clones within a single call of
the enclosing sub.

--

Father Chrysostomos

Tom Christiansen

unread,
Jul 7, 2012, 10:52:14 PM7/7/12
to perlbug...@perl.org, perl5-...@perl.org, perl6-l...@perl.org, dam...@conway.org
"Father Chrysostomos via RT" <perlbug...@perl.org> wrote
on Sat, 07 Jul 2012 18:54:15 PDT:


>Thank you. So the bar sub seems to be closing over the name @a (the
>container/variable slot/pad entry/whatever), rather than the actual
>array itself.

>Since I don't have it installed, could you tell me what this does?

All three of those say the same thing:

123
456

--tom

Father Chrysostomos via RT

unread,
Jul 8, 2012, 3:14:36 AM7/8/12
to perl5-...@perl.org, perl6-l...@perl.org, tch...@perl.com, dam...@conway.org
On Sat Jul 07 22:23:16 2012, thoughtstream wrote:
> Father Chrysostomos asked:
>
> > What I am really trying to find out is when the subroutine is actually
> > cloned,
>
> Yes. It is supposed to be (or at least must *appear* to be),
> and currently is (or appears to be) in Rakudo.

I said when, not whether. :-)

> > and whether there can be multiple clones within a single call of
> > the enclosing sub.
>
> Yes. For example, a lexical sub might be declared in a loop inside the
> enclosing sub, in which case it should produce multiple instances, one
> per iteration.
>
> For example, this:
>
> sub outer_sub () {
> for (1..3) {
> state $call_num = 1;
> my sub inner_sub {
> state $inner_state = (1..100).pick; # i.e. random number
> say " [call {$call_num++}] \$inner_state =
$inner_state";
> }
>
> say "\nsub id: ", &inner_sub.id;
> inner_sub();
> inner_sub();
> }
> }
>
> outer_sub();
>
> produces:
>
> sub id: -4628941774842748435
> [call 1] $inner_state = 89
> [call 2] $inner_state = 89
>
> sub id: -4628941774848253711
> [call 3] $inner_state = 16
> [call 4] $inner_state = 16
>
> sub id: -4628941774839825925
> [call 5] $inner_state = 26
> [call 6] $inner_state = 26
>
> under Rakudo

Thank you.

Does Perl 6 have an equivalent to this?

my $x;
for $x(1..10) {}

In this case, the loop reuses the $x slot in the pad, making the
existing $x name an alias to a different scalar. But, due to the way
Perl 5 closures work, it is, for all tents and porpoises, the same as this:

my $x;
for my $x(1..10) {}

> BTW, Both the above "yes" answers are consistent with (and can be
> inferred from) the previous explanation that:
>
> my sub foo { whatever() }
>
> is just a syntactic convenience for:
>
> my &foo := sub { whatever() }

Except that my sub foo happens upon block entry, right?

>
> HTH,

It does, but I am still trying to wrap my head around the fundamental
difference between 5 and 6 with regard to closures.

In Perl 5, $] in a piece of code is bound to *], not $], so it sees
changes made by local($]) (which actually puts a completely new scalar
in the *]{SCALAR} slot). But ‘my $x; sub { $x }’ is bound, not to the
$x slot in the outer block/sub/file, but to the actual scalar itself.

It seems that Perl 6 closures close over the slot, not the
scalar/array/etc. Is that right?

Anyway, I think I know how to implement this now.

The first time a ‘my’ sub is referenced or called, it is cloned. The
clone is stored for reuse, but that storage is localised to the current
block.

--

Father Chrysostomos

Father Chrysostomos via RT

unread,
Jul 8, 2012, 3:57:12 PM7/8/12
to perl5-...@perl.org, perl6-l...@perl.org, tch...@perl.com, dam...@conway.org, mor...@faui2k3.org
On Sun Jul 08 02:13:13 2012, thoughtstream wrote:
> Father Chrysostomos pointed out:
>
> > I said when, not whether. :-)
>
> Isn't that just typical of me: confusing ontology with chronology. ;-)
>
> I'm afraid don't know the implementation details for Rakudo. It may be
> bound as the surrounding block is entered, or perhaps just-in-time when
> the Code object is first accessed in some way.
>
>
> > Does Perl 6 have an equivalent to this?
> >
> > my $x;
> > for $x(1..10) {}
>
> In Perl 6 that's:
>
> my $x;
> for 1..10 -> $x {}
>
> And, as in Perl 5, they're two separate variables.

But by using the term ‘variable’, which is ambiguous, you are not
answering my question! :-)

In Perl 5, ‘my $x; for $x(1..10){}’ is only equivalent to ‘my $x; for my
$x(1..10){}’ because we don’t have the := operator, so there is never
any possibility to see the difference, even though things happen
differently underneath.

Does

my $x;
for 1..10 -> $x {}

cause the existing name $x to refer temporarily to each of the numbers,
or is a new $x name created?

What does this do?

my $x;
my sub f { say $x }
for 1..10 -> $x { f(); }

--

Father Chrysostomos

Father Chrysostomos via RT

unread,
Jul 8, 2012, 4:38:21 PM7/8/12
to perl5-...@perl.org, da...@iabyn.com
Based on feedback from Damian Conway about how these work in Perl 6 and
how they interact with state variables, I am now of the opinion that
‘my’ subs need to close over their variables whenever the enclosing
block is entered.

Since ‘my’ creates a new variable for each iteration of a loop, ‘my sub’
should create a new sub for each iteration.

And for consistency with my variables, a lexical sub that is closed over
by a named sub needs to appear ‘pre-cloned’, unless it is inside an
anonymous sub.

In Perl 6, the sub is created when the enclosing block is entered, which
is when the sub becomes visible. Perl 5 scoping is different. You
don’t see the sub until after the ‘my sub’. So I was going to say that
the variables are closed over when the name comes into scope. But that
model falls apart when you use goto to jump over the sub definition,
either forwards or backwards. If you do that, when exactly does the
name become visible?

My earlier idea for dwimming with:

my $x;
my sub f { warn $x };
for $x (1..10) { f(); }

and making it print 1 to 10 cannot work, because it would require
cloning the sub every time it is called. That cannot happen, because it
may contain state variables, which would not be shared between
instances. (for (1..10) { my sub f { state $x } } *should* create
separate state variables, otoh, because there are ten separate subs.)

So this is what we end up with (these are all the weirdest edge cases I
could think of):

Assume this for all examples:

sub p { print shift//undef, "\n" }

The f sub binds to the original $x, printing ‘undef’ ten times:

my $x;
my sub f { p $x }
for $x(1..10) {
f();
}

Here the f sub binds to the new $x in each iteration, printing 1 to 10:

my $x;
for $x(1..10) {
my sub f { p $x }
f();
}

The named sub closes over the first instance of m, as it would with my
$scalar, causing "yes" to be printed:

{
my sub m { p "yes" }
sub o { m() }
}
o();

Here, the block containing the m sub has never been entered, but its
enclosing CV is running, so the m sub is visible, but closes over an
undefined $x, printing ‘undef’:

o();
{
my $x = 42;
my sub m { p $x }
sub o { m() }
}

In this example, the block containing the m sub is the body of an
anonymous sub, so we get a ‘Subroutine m is not available’ warning, and
‘Undefined subroutine &m called’:

o();
sub {
my sub m { p "not ok" }
sub o { m() }
}

Since this prints 3:

o();
BEGIN {
my $x = 3;
sub o { p $x }
}

This should do the same:

o();
BEGIN {
my $x = 3;
my sub m { p $x }
sub o { m() }
}

To go back to the earlier example (without the BEGIN block or anon sub),
if we move the call after the block, we get 3 here, too:

{
my $x = 3;
my sub m { p $x }
sub o { m() }
}
o();

just as we do in this case:

{
my $x = 3;
sub o { p $x }
}
o();

--

Father Chrysostomos

Dave Mitchell

unread,
Jul 13, 2012, 4:20:28 PM7/13/12
to Father Chrysostomos via RT, perl5-...@perl.org
On Sun, Jul 08, 2012 at 01:38:21PM -0700, Father Chrysostomos via RT wrote:
> Based on feedback from Damian Conway about how these work in Perl 6 and
> how they interact with state variables, I am now of the opinion that
> ‘my’ subs need to close over their variables whenever the enclosing
> block is entered.
[snip]
> Here, the block containing the m sub has never been entered, but its
> enclosing CV is running, so the m sub is visible, but closes over an
> undefined $x, printing ‘undef’:
>
> o();
> {
> my $x = 42;
> my sub m { p $x }
> sub o { m() }
> }

I would expect it to instead to complain about calling an undefined
function instead; i.e. at the point of calling m(), m exists but has not
yet been defined.

Other than that, I agree with all your examples. Note that if you change
the one example above to my interpretation, then *every* edge case you
listed behaves identically as if you'd replaced

my sub m {...}

with

my $m = sub { ...};

Finally, what do you intend to happen regarding cloning with code like:

FOO:
my sub m { ... }
m();
goto FOO if ...;

I think redo may invoke a similar issue.

--
Technology is dominated by two types of people: those who understand what
they do not manage, and those who manage what they do not understand.

Father Chrysostomos via RT

unread,
Jul 13, 2012, 6:54:44 PM7/13/12
to perl5-...@perl.org, da...@iabyn.com
Like ‘sub foo’, ‘my sub foo’ will be a compile-time declaration. For
scoping to obey its usual rules, this will have to work:

my sub m;
sub m { ... } # attaches to lexical &m

And for ‘sub m’ to be a compile-time directive only sometimes does not
seem right.

So I was going to clone my subs on block entry (already partially done
locally). In the example you gave, the ‘my sub’ line is never actually
executed. So you get the same m sub after the goto.

Likewise, this should work, too:

my sub m;
m();
sub m { ... }

What happens in cases like this?

sub foo {
my $x;
sub bar { ... }
}

Does bar see the first $x?

Now back to this example:

> > o();
> > {
> > my $x = 42;
> > my sub m { p $x }
> > sub o { m() }
> > }

What if you change ‘my sub’ to ‘state sub’? What would you expect then?

Also, if the o sub can see the first instance of $x, should it not see
the first &m? (Don’t forget that you can’t exactly assign over a sub.)

And another issue which is currently impeding progress:

Following existing scoping rules, but with a twist due to ‘sub m’ being
a compile-time declaration, I would expect

my sub m;
my sub n {
sub m { ... }
}

to define the m sub at compile time. What should happen in that case is
fairly straightforward. The declaration works its way out to the pad
entry, just like regular variable lookup.

But then things become very confusing in cases like these:

sub {
my sub m;
sub {
eval 'sub m {...}';
}
}->()();

sub {
my sub m;
sub foo {
eval 'sub m {...}';
}
}
foo();

How far does the declaration make its way outward looking for its pad
entry? Does it stop at the first running sub?

I’m tempted to ignore that case for now and just see how the
implementation ends up doing it.

This is all making my head spin.

--

Father Chrysostomos

Dave Mitchell

unread,
Jul 18, 2012, 12:30:03 PM7/18/12
to Father Chrysostomos via RT, perl5-...@perl.org
On Fri, Jul 13, 2012 at 03:54:44PM -0700, Father Chrysostomos via RT wrote:
[stuff]

Before I try to reply to that, just as a data point, to what extent (if
any) do you consider the behaviour of 'my/state sub' in the following:

my sub foo;
my sub foo { ... };
foo();

state sub bar { ... };
bar();

to be different in behaviour or semantics to the following:

my $foo;
$foo = sub { ... };
$foo->();

state $bar = sub { ... };
$bar->();

apart from that at run-time, the assignment happens at the point of block
entry rather than at the point where the declaration is reached?

--
The warp engines start playing up a bit, but seem to sort themselves out
after a while without any intervention from boy genius Wesley Crusher.
-- Things That Never Happen in "Star Trek" #17

Reini Urban

unread,
Jul 18, 2012, 3:31:12 PM7/18/12
to Dave Mitchell, Father Chrysostomos via RT, perl5-...@perl.org
On Wed, Jul 18, 2012 at 11:30 AM, Dave Mitchell <da...@iabyn.com> wrote:
> On Fri, Jul 13, 2012 at 03:54:44PM -0700, Father Chrysostomos via RT wrote:
> [stuff]
>
> Before I try to reply to that, just as a data point, to what extent (if
> any) do you consider the behaviour of 'my/state sub' in the following:
>
> my sub foo;
> my sub foo { ... };
> foo();
>
> state sub bar { ... };
> bar();
>
> to be different in behaviour or semantics to the following:
>
> my $foo;
> $foo = sub { ... };
> $foo->();
>
> state $bar = sub { ... };
> $bar->();
>
> apart from that at run-time, the assignment happens at the point of block
> entry rather than at the point where the declaration is reached?

The only real usecase for lexical subs I see is for private methods in
package blocks.

package bla {
my sub _get { ... }
sub get { shift->_get(); ... }
sub new { bless {@_} }
}

And $blaobj->_get is run-time invalid (unless _get is a public method upwards).
Calling outside the block bla::_get() is even a compile-time error.

decl vs assign
==========
decl:
my sub foo; #forward decl
my sub foo { ... };
foo();

state sub bar { ... }; #normal decl
bar();

vs. assignment:
my $foo; #scalar decl
$foo = sub { ... }; #oh it's a lexical cv
$foo->();

state $bar = sub { ... };
$bar->();

to be consistent with other scalar assignments, the 2nd case is done naturally
- at the point where the declaration is reached, and the 1st case also.
Otherwise we would not need to do forward declarations.

As we are here at basic OO:
const %bla:: (readonly stash) will also protect you from using wrong
accessors, as they
will be detected at compile-time. This will hopefully convince people
not to use slow and
big accessor methods for everything which can be done by using simple hash
accessors directly. Unless you are planning to use the MOP.

const package bla {
my $attr1; # private attribute
our $attr2; # public attribute
sub new { bless {@_} }
}
$bla = new bla;
$bla->{attr2} = 1;
$bla->{attr1} = 0;
=> Attempt to access disallowed key 'attr1' in restricted hash

For your unpatched perls:
$ perl -MConst::Fast -e'const %a => (0=>1,1=>2); $a{2}=0';
Attempt to access disallowed key '2' in a restricted hash at -e line 1.

Because the semantics do not work yet and the syntax is awful:
$ perl -e'package a; our $a; package main;
Internals::SvREADONLY(%a::); print $a{b}';
=> no error
--
Reini Urban
http://cpanel.net/ http://www.perl-compiler.org/

Father Chrysostomos via RT

unread,
Jul 25, 2012, 7:00:54 PM7/25/12
to perl5-...@perl.org, da...@iabyn.com
On Wed Jul 18 09:31:10 2012, davem wrote:
> On Fri, Jul 13, 2012 at 03:54:44PM -0700, Father Chrysostomos via RT
wrote:
> [stuff]
>
> Before I try to reply to that, just as a data point, to what extent (if
> any) do you consider the behaviour of 'my/state sub' in the following:
>
> my sub foo;
> my sub foo { ... };
> foo();
>
> state sub bar { ... };
> bar();
>
> to be different in behaviour or semantics to the following:
>
> my $foo;
> $foo = sub { ... };
> $foo->();
>
> state $bar = sub { ... };
> $bar->();
>
> apart from that at run-time, the assignment happens at the point of block
> entry rather than at the point where the declaration is reached?

I hadn’t thought about it that way, but they are more or less equivalent
(except for when the assignment happens).

I also think now that a &foo pad entry visible to a named sub before
that block is entered should contain a sub stub. When the block is
entered, the prototype is cloned into the existing stub, resulting in
scoping nearly identical to lexical scalars.

--

Father Chrysostomos

Father Chrysostomos via RT

unread,
Jul 25, 2012, 7:06:00 PM7/25/12
to perl5-...@perl.org, rur...@x-ray.at
On Wed Jul 18 12:31:38 2012, rurban wrote:
> The only real usecase for lexical subs I see is for private methods in
> package blocks.
>
> package bla {
> my sub _get { ... }
> sub get { shift->_get(); ... }
> sub new { bless {@_} }
> }
>
> And $blaobj->_get is run-time invalid (unless _get is a public method
> upwards).
> Calling outside the block bla::_get() is even a compile-time error.

That would be _get($blaobj), not $blaobj->_get. If it’s private, it’s
not really a method, so it doesn’t add anything except confusion to call
it as one. And to make ->foo starting binding over lexical subs would
prevent calling a ->foo method on an unrelated object.

>
> decl vs assign
> ==========
> decl:
> my sub foo; #forward decl
> my sub foo { ... };
> foo();
>
> state sub bar { ... }; #normal decl
> bar();
>
> vs. assignment:
> my $foo; #scalar decl
> $foo = sub { ... }; #oh it's a lexical cv
> $foo->();
>
> state $bar = sub { ... };
> $bar->();
>
> to be consistent with other scalar assignments, the 2nd case is done
> naturally
> - at the point where the declaration is reached, and the 1st case
> also.
> Otherwise we would not need to do forward declarations.

Cloning the sub on block entry but making it visible only within the
scope starting with the first declaration effectively does that, but
avoids the problem of ‘goto’ jumping over the declaration (either
forwards or backwards).

>
> As we are here at basic OO:
> const %bla:: (readonly stash) will also protect you from using wrong
> accessors, as they
> will be detected at compile-time. This will hopefully convince people
> not to use slow and
> big accessor methods for everything which can be done by using simple
> hash
> accessors directly. Unless you are planning to use the MOP.
>
> const package bla {
> my $attr1; # private attribute
> our $attr2; # public attribute
> sub new { bless {@_} }
> }
> $bla = new bla;
> $bla->{attr2} = 1;
> $bla->{attr1} = 0;
> => Attempt to access disallowed key 'attr1' in restricted hash

You seem to be conflating variables and hash keys, which in Perl (unlike
JavaScript) are orthogonal concepts.

>
> For your unpatched perls:
> $ perl -MConst::Fast -e'const %a => (0=>1,1=>2); $a{2}=0';
> Attempt to access disallowed key '2' in a restricted hash at -e line
> 1.
>
> Because the semantics do not work yet and the syntax is awful:
> $ perl -e'package a; our $a; package main;
> Internals::SvREADONLY(%a::); print $a{b}';
> => no error

SvREADONLY means about three different things (restricted hash, COW, and
actually read-only). If we want that to work, we might need to
disentangle those meanings first.

--

Father Chrysostomos

Father Chrysostomos via RT

unread,
Jul 29, 2012, 11:41:59 PM7/29/12
to perl5-...@perl.org, da...@iabyn.com
On Wed Jul 25 16:00:54 2012, sprout wrote:
> I also think now that a &foo pad entry visible to a named sub before
> that block is entered should contain a sub stub. When the block is
> entered, the prototype is cloned into the existing stub, resulting in
> scoping nearly identical to lexical scalars.

But here is an interesting question. What happens in this case?

my sub foo ($) {}
BEGIN {
warn defined &foo ? "defined" : "undefined";

# What happens here???
warn prototype \&foo;
}

From an implementation standpoint, it is easier for the prototype not to
be visible before the scope is entered, making it comparable to:

sub foo; # at compile time
eval 'sub foo($) {}' # on scope entry

rather than:

sub foo($);
eval 'sub foo($) {}'

--

Father Chrysostomos

Rev. Chip

unread,
Jul 30, 2012, 12:04:55 AM7/30/12
to Father Chrysostomos via RT, perl5-...@perl.org, da...@iabyn.com
I think the hard thing is the necessary thing here. You'll have to sneak
the prototype into the padname at compile time somehow, or else create a
stub CV to hold it.... Ugly, I know.
--
Chip Salzenberg

Father Chrysostomos via RT

unread,
Jul 30, 2012, 1:44:52 AM7/30/12
to perl5-...@perl.org, rev....@gmail.com
On Sun Jul 29 21:05:46 2012, rev....@gmail.com wrote:
> On Sun, Jul 29, 2012 at 08:41:59PM -0700, Father Chrysostomos via RT
wrote:
> > On Wed Jul 25 16:00:54 2012, sprout wrote:
> > > I also think now that a &foo pad entry visible to a named sub before
> > > that block is entered should contain a sub stub. When the block is
> > > entered, the prototype is cloned into the existing stub, resulting in
> > > scoping nearly identical to lexical scalars.
> >
> > But here is an interesting question. What happens in this case?
> >
> > my sub foo ($) {}
> > BEGIN {

I meant to mention here that this line emits ‘undefined’:

> > warn defined &foo ? "defined" : "undefined";
> >
> > # What happens here???
> > warn prototype \&foo;
> > }
> >
> > From an implementation standpoint, it is easier for the prototype not to
> > be visible before the scope is entered, making it comparable to:
> >
> > sub foo; # at compile time
> > eval 'sub foo($) {}' # on scope entry
> >
> > rather than:
> >
> > sub foo($);
> > eval 'sub foo($) {}'
>
> I think the hard thing is the necessary thing here.

Why necessary?

> You'll have to sneak
> the prototype into the padname at compile time somehow, or else create a
> stub CV to hold it.... Ugly, I know.

Right now I’m putting a stub in the pad slot, with a prototype CV
attached to it via magic.

On scope entry, a variant of cv_clone is called that clones the
prototype CV into the existing stub (instead of creating a new CV on the
fly).

So what I’ve decided to call the parameter prototype to avoid confusion
(i.e., the ($) in sub foo($)) is attached to the prototype CV, which
also has the op tree. It is cloned just like an anonymous closure.

If I have to attach the parameter prototype to the stub initially, as
well as to the prototype CV, things get complicated. That’s why I ask
above, why necessary?

BTW, in

my sub foo($);
sub foo($) { }

the first declaration sets up a stub CV in the pad slot, with another
stub attached to it via magic. The second stub holds the parameter
prototype. The second declaration attaches the body of the sub to the
second stub, not the first.

--

Father Chrysostomos

Father Chrysostomos via RT

unread,
Aug 3, 2012, 7:08:41 PM8/3/12
to perl5-...@perl.org, da...@iabyn.com
This program:

#!perl -w
sub foo {
my $x;
print $x, "\n";
sub bar { $x = 3 }
}
bar;
foo;

outputs this:

Variable "$x" will not stay shared at - line 4.
3

But this one:

#!perl -w
sub foo {
my $x;
print $x, "\n";
sub bar { sub { $x = 3 }->() }
}
bar;
foo;

outputs this:

Variable "$x" will not stay shared at - line 5.
Variable "$x" is not available at - line 5.
Use of uninitialized value $x in print at - line 4.
<blank line>

Is this discrepancy necessary? To me ‘Variable "$x" is not available’
makes sense if the outer sub is a closure prototype (CvCLONE &&
!CvCLONED), but if it is a callable sub, I don’t see why this needs to
happen. And it leads to the discrepancy shown above.

The reason I bring this up is that the very same code paths cause this
(on the sprout/lexsub branch):

$ ./miniperl -lw -e' sub foo { my $x = shift; my sub x { $x } \&x }
print foo->()'
Variable "$x" is not available at -e line 1.
Use of uninitialized value in print at -e line 1.
<blank line>

because the x sub is cloned when foo enters, and $x is still marked stale.

Is it ok to change this? (Doing so would also allow me to remove the
clonecv op type. Right now the sprout/lexsub branch creates two ops
[introcv and clonecv] on scope entry for every my sub in that scope.)
--

Father Chrysostomos

Father Chrysostomos via RT

unread,
Aug 4, 2012, 2:21:05 AM8/4/12
to perl5-...@perl.org, da...@iabyn.com, ni...@ccl4.org
Interestingly, adf8f095c588 caused a behaviour change:

sub foo {
my $x;
sub bar {
$x = 3;
print $x, "\n";
sub { print $x, "\n" }->()
}
}
bar();

$ pbpaste|perl5.14.0
3

$ pbpaste|perl5.12.0
3
3

I think that is plainly a bug, that this:

print $x, "\n";
sub { print $x, "\n" }->()

could output two different values.


adf8f095c588 was:

commit adf8f095c5881bcedf07b8e41072f8125e00b5a6
Author: Nicholas Clark <ni...@ccl4.org>
Date: Fri Feb 26 09:18:44 2010 +0000

Set PADSTALE on all lexicals at the end of sub creation.

The PADSTALEness of lexicals between the 0th and 1st call to a
subroutine is now
consistent with the state between the nth and (n + 1)th call.

This permits a work around in Perl_padlist_dup() to avoid leaking
active pad
data into a new thread, whilst still correctly bodging the external
references
needed by the current ?{} implementation. Fix that, and this can be
removed.


I don’t know whether this affects my subs yet, but I would like to gain
a better understanding of this commit. How did ?{} blocks work before?
What exactly was the fix intended to do?

--

Father Chrysostomos

Father Chrysostomos via RT

unread,
Aug 4, 2012, 9:43:00 AM8/4/12
to perl5-...@perl.org, da...@iabyn.com, ni...@ccl4.org
I can reproduce this bug even further back:

sub foo {
my $x if @_;
return if @_;

$x = 17;
print $x, "\n";
print sub { $x }->(), "\n";
return;

}
foo(1); # make $x stale in all perl versions
foo;

$ pbpaste|perl5.10.1 -w
17
Variable "$x" is not available at - line 7.
Use of uninitialized value in print at - line 7.

$ pbpaste|perl5.10.0 -w
17
17

--

Father Chrysostomos

Father Chrysostomos via RT

unread,
Aug 4, 2012, 9:03:27 PM8/4/12
to perl5-...@perl.org
I’ve fixed both those issues with commit cae5dbbe3.

--

Father Chrysostomos

Father Chrysostomos via RT

unread,
Aug 12, 2012, 9:22:14 PM8/12/12
to perl5-...@perl.org
What should this do?

sub foo {
my $x = 23;
my sub bar;
sub {
sub bar { $x } # my sub bar is in scope, so this defines its body
};
warn bar();
}
foo();

My first thought was that, since bar is cloned when foo is called, it
should see foo’s $x.

I could make it work that way, but implementing it is quite complicated.

bar’s CvOUTSIDE pointer points to the prototype CV for the anonymous sub
containing its definition. Usually, when a sub is cloned, any pad entry
marked FAKE (meaning it belongs to the outer sub) just ends up
referencing the same SV that is in the outer sub’s pad, unless the outer
pad is inactive. In this case, the anonymous prototype has an entry for
$x, but it is empty.

So the cloning code would have to follow the CvOUTSIDE chain until it
finds an active sub.

That might make the above example work, but this slightly different one
would require more complicated checks:

sub {
my $x = 23;
my sub bar;
sub {
sub bar { $x } # my sub bar is in scope, so this defines its body
};
warn bar();
}->();

The outermost sub is an anonymous sub. Therefore the inner anonymous
prototype’s CvOUTSIDE pointer points to the outer prototype CV, not its
currently-running clone. So, in addition to following CvOUTSIDE
pointers, we would also have to search the context stack for the
currently-running clone.

I don’t think it is worth it. Both examples above should warn with
‘Variable "$x" is not available’. Opinions?

--

Father Chrysostomos

Father Chrysostomos via RT

unread,
Aug 23, 2012, 12:40:57 PM8/23/12
to perl5-...@perl.org
On Fri Aug 03 16:08:40 2012, sprout wrote:
Just for future reference: I have found that I do still need two
separate ops for introcv and clonecv.

sub {
my sub s1;
my sub s2;
sub s1 { state sub foo { \&s2 } }
}->()

/* pad_leavemy has created a sequence of introcv ops for all my
subs declared in the block. We have to replicate that list with
clonecv ops, to deal with this situation:

sub {
my sub s1;
my sub s2;
sub s1 { state sub foo { \&s2 } }
}->()

Originally, I was going to have introcv clone the CV and turn
off the stale flag. Since &s1 is declared before &s2, the
introcv op for &s1 is executed (on sub entry) before the one for
&s2. But the &foo sub inside &s1 (which is cloned when &s1 is
cloned, since it is a state sub) closes over &s2 and expects
to see it in its outer CV’s pad. If the introcv op clones &s1,
then &s2 is still marked stale. Since &s1 is not active, and
&foo closes over &s1’s implicit entry for &s2, we get a ‘Varia-
ble will not stay shared’ warning. Because it is the same stub
that will be used when the introcv op for &s2 is executed, clos-
ing over it is safe. Hence, we have to turn off the stale flag
on all lexical subs in the block before we clone any of them.
Hence, having introcv clone the sub cannot work. So we create a
list of ops like this:

lineseq
|
+-- introcv
|
+-- introcv
|
+-- introcv
|
.
.
.
|
+-- clonecv
|
+-- clonecv
|
+-- clonecv
|
.
.
.
*/


--

Father Chrysostomos

Reverend Chip

unread,
Aug 23, 2012, 10:13:06 PM8/23/12
to perl5-...@perl.org
On 8/12/2012 6:22 PM, Father Chrysostomos via RT wrote:
> I don’t think it is worth it. Both examples above should warn with
> ‘Variable "$x" is not available’. Opinions?

I'd have thought the primary error is that I have no reason to demand
that "sub bar" should work when it's not in the same scope as the
declaration "my sub bar". But if I'm out of date on that thought, then
yes, I certainly wouldn't complain if $x is not available.

Father Chrysostomos via RT

unread,
Aug 24, 2012, 1:23:57 AM8/24/12
to perl5-...@perl.org, rev....@gmail.com
On Thu Aug 23 19:13:47 2012, rev....@gmail.com wrote:
> On 8/12/2012 6:22 PM, Father Chrysostomos via RT wrote:
> > I don’t think it is worth it. Both examples above should warn with
> > ‘Variable "$x" is not available’. Opinions?
>
> I'd have thought the primary error is that I have no reason to demand
> that "sub bar" should work when it's not in the same scope as the
> declaration "my sub bar".

It would be useful to be able to redefine the subroutine at run time:

sub foo {
my sub bar;
eval 'sub bar {' . $stuff . '}';
}

If it can go inside an eval, then why not a compile-time declaration in
an inner sub or block eval?

> But if I'm out of date on that thought, then
> yes, I certainly wouldn't complain if $x is not available.

--

Father Chrysostomos

Father Chrysostomos via RT

unread,
Sep 9, 2012, 2:51:43 AM9/9/12
to perl5-...@perl.org
There are still some things that need to be looked into, but they are
bizarre edge cases unlikely to occur in real code.

I would like to merge this to blead fairly soon (once I write
documentation), so there is plenty of time to shake out bugs (or design
flaws) before 5.18.

In the mean time, you can try out the sprout/lexsub branch.

Have the fitting amount of enjoyment.

--

Father Chrysostomos

Reverend Chip

unread,
Sep 9, 2012, 3:59:28 AM9/9/12
to perlbug...@perl.org, perl5-...@perl.org
On 8/23/2012 10:23 PM, Father Chrysostomos via RT wrote:
> On Thu Aug 23 19:13:47 2012, rev....@gmail.com wrote:
>> On 8/12/2012 6:22 PM, Father Chrysostomos via RT wrote:
>>> I don’t think it is worth it. Both examples above should warn with
>>> ‘Variable "$x" is not available’. Opinions?
>> I'd have thought the primary error is that I have no reason to demand
>> that "sub bar" should work when it's not in the same scope as the
>> declaration "my sub bar".
> It would be useful to be able to redefine the subroutine at run time:
>
> sub foo {
> my sub bar;
> eval 'sub bar {' . $stuff . '}';
> }

That's a nicety I would have been willing to do without but ... OK,
thank you.

Father Chrysostomos via RT

unread,
Sep 10, 2012, 5:48:00 PM9/10/12
to perl5-...@perl.org
Is there any reason PL_comppad_name should not be set at run time, like
PL_comppad? I presume it is not currently set because nothing is using it.

If we could set it in pp_entersub, I could simplify the lexical sub
implementation, reducing it by about a hundred lines.

--

Father Chrysostomos

Father Chrysostomos via RT

unread,
Sep 10, 2012, 9:06:27 PM9/10/12
to perl5-...@perl.org, perl...@rjbs.manxome.org
On Mon Sep 10 17:03:10 2012, perl...@rjbs.manxome.org wrote:
> * Father Chrysostomos via RT <perlbug...@perl.org> [2012-09-
> 09T02:51:43]
> > There are still some things that need to be looked into, but they
> are
> > bizarre edge cases unlikely to occur in real code.
> >
> > I would like to merge this to blead fairly soon (once I write
> > documentation), so there is plenty of time to shake out bugs (or
> design
> > flaws) before 5.18.
> >
> > In the mean time, you can try out the sprout/lexsub branch.
>
> I look forward to playing with it!
>
> This strikes me as exactly the sort of thing that belongs behind 'use
> experimental'

Like this?

package experimental;

$VERSION = '0.01';

my %features = (
lexical_subs => 0x20000000,
);

BEGIN { $^H |= 0x20000000 }

my sub croak {
require Carp;
Carp::croak("Unknown experimental feature: $_[0]");
}

sub import {
$^H |= $features{$_} || croak($_) for @_[1..$#_];
}

sub unimport {
$^H &= ~($features{$_} || croak($_)) for @_[1..$#_];
}

sub features { wantarray ? sort keys %features : keys %features }

my(undef)=(undef) # return a true value

__END__

> at least before it hits Real Production, because it's a
> big,
> complex, *experimental* feature that we might want to turn off without
> having
> to go through a big deprecation cycle in case of future epiphany.

OK, should that apply only to declaration of such subs (my sub foo), or
also to name lookup (hiding lexical subs registered by XS modules)?

Disabling the former under a pragma is trivial. Disabling the latter is
far from it. (It’s doable, but has to be done in enough places, and
slightly differently in each, that it would relegate all symbol lookup
to experimental status. :-)

--

Father Chrysostomos

Steffen Mueller

unread,
Sep 11, 2012, 1:47:25 AM9/11/12
to perlbug...@perl.org, perl5-...@perl.org, perl...@rjbs.manxome.org
On 09/11/2012 03:06 AM, Father Chrysostomos via RT wrote:
[lexical subs discussion]
>> at least before it hits Real Production, because it's a
>> big,
>> complex, *experimental* feature that we might want to turn off without
>> having
>> to go through a big deprecation cycle in case of future epiphany.
>
> OK, should that apply only to declaration of such subs (my sub foo), or
> also to name lookup (hiding lexical subs registered by XS modules)?
>
> Disabling the former under a pragma is trivial. Disabling the latter is
> far from it. (It’s doable, but has to be done in enough places, and
> slightly differently in each, that it would relegate all symbol lookup
> to experimental status. :-)

Clearly only disable the syntax. It's the only sane trade-off.

Slightly tongue in cheek, what's the difference between
use experimental 'foo';
and
use Crazy::XS::Module::That::You::Installed::From::CPAN 'myfoo';
?

Either way, you're asking for it.

--Steffen

Jesse Luehrs

unread,
Sep 11, 2012, 1:55:33 AM9/11/12
to Steffen Mueller, perlbug...@perl.org, perl5-...@perl.org, perl...@rjbs.manxome.org
Mostly that not everything can be done with XS - consider things like
'unicode_strings' or 'dot'.

-doy

Steffen Mueller

unread,
Sep 11, 2012, 2:36:46 AM9/11/12
to Jesse Luehrs, perlbug...@perl.org, perl5-...@perl.org, perl...@rjbs.manxome.org
On 09/11/2012 07:55 AM, Jesse Luehrs wrote:
> On Tue, Sep 11, 2012 at 07:47:25AM +0200, Steffen Mueller wrote:
>> On 09/11/2012 03:06 AM, Father Chrysostomos via RT wrote:
>> [lexical subs discussion]
>>>> at least before it hits Real Production, because it's a
>>>> big,
>>>> complex, *experimental* feature that we might want to turn off without
>>>> having
>>>> to go through a big deprecation cycle in case of future epiphany.
>>>
>>> OK, should that apply only to declaration of such subs (my sub foo), or
>>> also to name lookup (hiding lexical subs registered by XS modules)?
>>>
>>> Disabling the former under a pragma is trivial. Disabling the latter is
>>> far from it. (It’s doable, but has to be done in enough places, and
>>> slightly differently in each, that it would relegate all symbol lookup
>>> to experimental status. :-)

^^^^ This is what I am referring to!

>> Clearly only disable the syntax. It's the only sane trade-off.
>>
>> Slightly tongue in cheek, what's the difference between
>> use experimental 'foo';
>> and
>> use Crazy::XS::Module::That::You::Installed::From::CPAN 'myfoo';
>> ?
>>
>> Either way, you're asking for it.
>
> Mostly that not everything can be done with XS - consider things like
> 'unicode_strings' or 'dot'.

I think you misread what I wrote or I expressed it poorly. I was trying to
argue that "use experimental 'foo'" should only disable the syntax since
anybody trying to get to the functionality another way (here: XS) would
anyway have to do something explicit to get it, so it's not worth worrying
about.

--Steffen

Father Chrysostomos via RT

unread,
Sep 11, 2012, 2:51:28 AM9/11/12
to perl5-...@perl.org, perl...@rjbs.manxome.org
On Mon Sep 10 17:03:10 2012, perl...@rjbs.manxome.org wrote:
> This strikes me as exactly the sort of thing that belongs behind 'use
> experimental' at least before it hits Real Production, because it's a
> big,
> complex, *experimental* feature that we might want to turn off without
> having
> to go through a big deprecation cycle in case of future epiphany.

On the sprout/lexsub branch, it is now controlled by ‘use experimental
"lexical_subs"’. Compared with implementing lexical subs themselves,
that was a breeze.

--

Father Chrysostomos

Leon Timmermans

unread,
Sep 11, 2012, 3:59:44 AM9/11/12
to Ricardo Signes, perl5-...@perl.org
On Tue, Sep 11, 2012 at 2:02 AM, Ricardo Signes
<perl...@rjbs.manxome.org> wrote:
> I look forward to playing with it!
>
> This strikes me as exactly the sort of thing that belongs behind 'use
> experimental' at least before it hits Real Production, because it's a big,
> complex, *experimental* feature that we might want to turn off without having
> to go through a big deprecation cycle in case of future epiphany.

How should experimental work in face of forward compatibility? I mean,
even if it's a feature in 5.20, would you still have to use
experimental if you want it to work on 5.18?

I think an experimental feature bundle inside feature.pm
(":experimental") that's not included in the version feature bundle
(':5.18') may be a more future-compatible approach.

Leon

David Golden

unread,
Sep 11, 2012, 6:46:35 AM9/11/12
to p5p
On Tue, Sep 11, 2012 at 3:59 AM, Leon Timmermans <faw...@gmail.com> wrote:
>
> How should experimental work in face of forward compatibility? I mean,
> even if it's a feature in 5.20, would you still have to use
> experimental if you want it to work on 5.18?

+1 for that thought

> I think an experimental feature bundle inside feature.pm
> (":experimental") that's not included in the version feature bundle
> (':5.18') may be a more future-compatible approach.

(Without great thought) I suspect that only works in concert with a
version declaration. C<< use v5.18; use feature ':experimental' >>.

These kinds of cases incresingly make me want to classify feature.pm
right up there with version.pm as things for which I wish we had a
time machine for a do-over.

David

--
David Golden <x...@xdg.me>
Take back your inbox! → http://www.bunchmail.com/
Twitter/IRC: @xdg

Dave Mitchell

unread,
Sep 11, 2012, 6:59:23 AM9/11/12
to Father Chrysostomos via RT, perl5-...@perl.org
Performance. Years ago when I were a lad, I wanted pp_entersub to
set PL_runcv to point to the current running CV, but was vetoed on these
grounds (and so wrote find_runcv() instead).

Note that the biggest cost in pp_entersub is pushing the new context entry
(and all its saved values), plus pushing some stuff on the save stack;
then restoring it all in pp_leavesub.

If we were to do something like this, I'd prefer that we recorded the
current running CV rather than PL_comppad_name, then used the CV to derive
PL_comppad_name when needed.

--
In my day, we used to edit the inodes by hand. With magnets.

Robert Sedlacek

unread,
Sep 11, 2012, 7:37:30 AM9/11/12
to perl5-...@perl.org
Would that be an all-or-nothing bundle for that version? That would lose
the explicit documentative nature of `use experimental 'lexical_subs';`

And if it were a real feature in 5.20, you'd have to have a way that
works with both 5.18 and 5.20. What if the experimental feature were
tied to the versions it was experimental on:

# works on 5.18, 5.20, +
use 5.18;
use experimental 'lexical_subs';

# fatal error "feature 'lexical_subs' no
# longer experimental since 5.20"
use 5.20;
use experimental 'lexical_subs';

regards,
--
Robert 'phaylon' Sedlacek

Perl 5 Consultant for
Shadowcat Systems Limited - http://shadowcat.co.uk/

Leon Timmermans

unread,
Sep 11, 2012, 7:44:35 AM9/11/12
to David Golden, p5p
On Tue, Sep 11, 2012 at 12:46 PM, David Golden <x...@xdg.me> wrote:
>> I think an experimental feature bundle inside feature.pm
>> (":experimental") that's not included in the version feature bundle
>> (':5.18') may be a more future-compatible approach.
>
> (Without great thought) I suspect that only works in concert with a
> version declaration. C<< use v5.18; use feature ':experimental' >>.

I'm not fond of complex interactions between use <version> and use
<some_pragma>. Maybe we should skip the experimental bundle
altogether, and force a user to be explicit if they want this feature.

Leon

demerphq

unread,
Sep 11, 2012, 9:39:25 AM9/11/12
to Ricardo Signes, perl5-...@perl.org
On 11 September 2012 15:00, Ricardo Signes <perl...@rjbs.manxome.org> wrote:
> * Father Chrysostomos via RT <perlbug...@perl.org> [2012-09-10T21:06:27]
>> Like this?
>>
>> package experimental;
>> ...
>
> Roughly. Someone else brought up the forward compatibility. I talked about
> this however-long-ago when talking about feature.pm's future, and suggested
> something like this (munged to be specific to this case):
>
> lexical sub declarations are allowed if feature experimental::lexical_subs
> is on
>
> use experimental 'lexical_subs' == use feature 'experimental::lexical_subs'
>
> when lexical_subs is non-experimental, it goes behind feature lexical_subs
>
> ...and experimental::lexical_subs is an alias to that
>
> This lets you write code using experimental::lexical_subs in 5.18 and have it
> keep working without editing in 5.20, the way we'd expect from an experimental
> feature today. If the experimental feature is killed, though, your code will
> have had to had that "use experimental" somewhere in it (or maybe "use feature
> 'experimental::...".)
>

Features may solve the 5.18 to 5.20 problem, they dont solve the "run
code written for 5.22 on 5.18 problem". In fact they seem to make it
unsolvable.

Yves

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

demerphq

unread,
Sep 11, 2012, 11:18:22 AM9/11/12
to Ricardo Signes, perl5-...@perl.org
On 11 September 2012 16:07, Ricardo Signes <perl...@rjbs.manxome.org> wrote:
> * demerphq <deme...@gmail.com> [2012-09-11T09:39:25]
>> Features may solve the 5.18 to 5.20 problem, they dont solve the "run
>> code written for 5.22 on 5.18 problem". In fact they seem to make it
>> unsolvable.
>
> What about providing a mechanism to plug in a handler saying "when somebody
> asks for this feature, do something."
>
> So, say "use feature 'banana'" enables the banana built-in. Later, someone
> writes Backport::Banana, which injects such a hook iff $] is too low to provide
> it natively.
>
> perl -MBackport::Banana my-program
>
> ---
>
> # my-program
> use feature 'banana';
>
> banana(123); # works
>
> Obviously not every feature is going to be backportable, but providing the
> above seems plausable at least at first blush.

I guess this is a strategy. But in a lot of cases IMO it would simply
to just use a namespace. After all namespaces were *invented* to solve
this problem.

demerphq

unread,
Sep 11, 2012, 11:36:07 AM9/11/12
to Ricardo Signes, perl5-...@perl.org
On 11 September 2012 17:29, Ricardo Signes <perl...@rjbs.manxome.org> wrote:
> * demerphq <deme...@gmail.com> [2012-09-11T11:18:22]
>> I guess this is a strategy. But in a lot of cases IMO it would simply
>> to just use a namespace. After all namespaces were *invented* to solve
>> this problem.
>
> Fair enough, and it shows especially that my banana example was even worse than
> was obvious at first. On the other hand, what about things that are changing
> syntax, like lexical subs?
>
> Would it be better (I ask, without opinion or much thought on the matter) if
> "use feature ':5.10'" was replaced with or equivalent to:
>
> feature::say->import;
> feature::state->import;
> feature::switch->import;
> etc;
>
> and then it would be possible to install a "compat" feature::say on your perl
> 5.8?
>
> Alternately: how do *you* think all this stuff should work?

Well, for things which alter perls parse behavior I dont see much we
can do better. Probably more clever people on list will.

However for utility subs, such as those from Mauve, we avoid that
*entire* discussion if we just treat them as preinstalled modules. At
that point on newer perls the module becomes a no-op, or outright
unnecessary if back-compat is not an issue. For code that must run on
older perls the module is not a no-op, instead it populates the
namespace itself.

I mean, this is all predicated that we dont really care where a sub
comes from, just that it is in the namespace we expect to find it in.

Jesse Luehrs

unread,
Sep 11, 2012, 11:45:18 AM9/11/12
to demerphq, Ricardo Signes, perl5-...@perl.org
On Tue, Sep 11, 2012 at 05:36:07PM +0200, demerphq wrote:
> On 11 September 2012 17:29, Ricardo Signes <perl...@rjbs.manxome.org> wrote:
> > * demerphq <deme...@gmail.com> [2012-09-11T11:18:22]
> >> I guess this is a strategy. But in a lot of cases IMO it would simply
> >> to just use a namespace. After all namespaces were *invented* to solve
> >> this problem.
> >
> > Fair enough, and it shows especially that my banana example was even worse than
> > was obvious at first. On the other hand, what about things that are changing
> > syntax, like lexical subs?
> >
> > Would it be better (I ask, without opinion or much thought on the matter) if
> > "use feature ':5.10'" was replaced with or equivalent to:
> >
> > feature::say->import;
> > feature::state->import;
> > feature::switch->import;
> > etc;
> >
> > and then it would be possible to install a "compat" feature::say on your perl
> > 5.8?
> >
> > Alternately: how do *you* think all this stuff should work?
>
> Well, for things which alter perls parse behavior I dont see much we
> can do better. Probably more clever people on list will.

With the work that's being done on the PL_keyword_plugin and core subs
stuff, most built-in keywords should be overridable at some point, with
whatever kinds of new syntax you want. Whether this is a maintainable
solution in the long run is a separate question, but it is at least
possible in theory.

> However for utility subs, such as those from Mauve, we avoid that
> *entire* discussion if we just treat them as preinstalled modules. At
> that point on newer perls the module becomes a no-op, or outright
> unnecessary if back-compat is not an issue. For code that must run on
> older perls the module is not a no-op, instead it populates the
> namespace itself.
>
> I mean, this is all predicated that we dont really care where a sub
> comes from, just that it is in the namespace we expect to find it in.

I've wanted to look into this sort of things for a while - we already
have code to autoload an implementation from an external module when a
certain feature is used (for arybase, %!, etc), so there's not really
any reason that we couldn't keep the implementation in a module, have it
autoloaded in newer perls, but provide compatibility with older perls by
requiring the module to be loaded explicitly.

This would actually probably be even more useful in the other direction
- remove things like dbmopen() from the core perl parser and split them
out into a module that is autoloaded on demand when the keyword is
actually used.

Lots of handwaving involved, clearly, but it seems like it could be
a pretty useful option.

-doy

demerphq

unread,
Sep 11, 2012, 11:50:43 AM9/11/12
to Jesse Luehrs, Ricardo Signes, perl5-...@perl.org
For me this misses a key point. Loading DLL's or SO's to get access to
core functionality is simply wasteful.

Recently we have seen how DLL/SO address collision impacts perl, why
would we want to *encourage* that waste?

Any non-trivial program ive seen ends up loading Scalar::Util to get
access to reftype or blessed().

Why do i have to load a DLL to do that?

Father Chrysostomos via RT

unread,
Sep 11, 2012, 11:51:17 AM9/11/12
to perl5-...@perl.org
Not at all. Just have a CPAN module that calls feature->import under
5.20 and Exporter->import under 5.18.

I think that is what any::feature is for. But it appears to be stalled.

--

Father Chrysostomos

Jesse Luehrs

unread,
Sep 11, 2012, 11:55:19 AM9/11/12
to demerphq, Ricardo Signes, perl5-...@perl.org
It's only wasteful if it's something you're going to use in the majority
of your programs. blessed() probably wouldn't benefit from something
like that, but what about things like set_prototype()? Or, considering
my next paragraph there, things like dbmopen() (or maybe even formats)?

It all depends on the definition of "core functionality".

-doy

demerphq

unread,
Sep 11, 2012, 1:00:55 PM9/11/12
to Jesse Luehrs, Ricardo Signes, perl5-...@perl.org
I assume you mean "would".

> like that, but what about things like set_prototype()? Or, considering
> my next paragraph there, things like dbmopen() (or maybe even formats)?

As soon as I start arguing stuff related to that should go in core we
can debate it. :-)

David Golden

unread,
Sep 11, 2012, 4:01:26 PM9/11/12
to Ricardo Signes, perl5-...@perl.org
On Tue, Sep 11, 2012 at 11:29 AM, Ricardo Signes
<perl...@rjbs.manxome.org> wrote:
> Would it be better (I ask, without opinion or much thought on the matter) if
> "use feature ':5.10'" was replaced with or equivalent to:
>
> feature::say->import;
> feature::state->import;
> feature::switch->import;
> etc;

Similarly without much thought... my gut reaction is positive.

I'm not sure if it can be made to work for all feature types, but the
way that feature.pm is highly orthogonal to how we manage extensions
already feels like a design smell.

Father Chrysostomos via RT

unread,
Sep 11, 2012, 5:12:01 PM9/11/12
to perl5-...@perl.org, perl...@rjbs.manxome.org
On Tue Sep 11 06:00:47 2012, perl...@rjbs.manxome.org wrote:
> * Father Chrysostomos via RT <perlbug...@perl.org> [2012-09-
OK, if you look at the sprout/lexsub branch *now*, you will find that
variation--and documentation, too!

> > my(undef)=(undef) # return a true value
>
> Now you're just baiting me!

Programming in Perl is supposed to be fun, no?

(I think your idea is better, but I never got to putting forth my idea
about an experimental warnings category. It would be on by default,
like deprecations [bugs aside, mumble mumble], but ‘no warnings
"experimental"’ would turn off the constant nagging.)

--

Father Chrysostomos

Aristotle Pagaltzis

unread,
Sep 11, 2012, 9:11:27 PM9/11/12
to perl5-...@perl.org
* Ricardo Signes <perl...@rjbs.manxome.org> [2012-09-11 15:05]:
> Roughly. Someone else brought up the forward compatibility. I talked
> about this however-long-ago when talking about feature.pm's future,
> and suggested something like this (munged to be specific to this
> case):
>
> lexical sub declarations are allowed if feature experimental::lexical_subs
> is on
>
> use experimental 'lexical_subs' == use feature 'experimental::lexical_subs'
>
> when lexical_subs is non-experimental, it goes behind feature lexical_subs
>
> ...and experimental::lexical_subs is an alias to that
>
> This lets you write code using experimental::lexical_subs in 5.18 and
> have it keep working without editing in 5.20, the way we'd expect from
> an experimental feature today. If the experimental feature is killed,
> though, your code will have had to had that "use experimental"
> somewhere in it (or maybe "use feature 'experimental::...".)

Heretical question: what makes an experimental feature anything else
than a regular feature that isn’t included in any version bundle? I.e.
why not just have the user write `use feature 'lexical_subs'` explicitly
in 5.18 to get it, but withhold it if they write just `use 5.018`? Then
if the experiment works out, it becomes part of the 5.20 or 5.22 feature
bundle, so `use 5.022` enables it by default.

With one fell swoop, forward compat is taken care of.

Tell me what I’m missing.

Regards,
--
Aristotle Pagaltzis // <http://plasmasturm.org/>

Aristotle Pagaltzis

unread,
Sep 11, 2012, 9:40:35 PM9/11/12
to perl5-...@perl.org
* Ricardo Signes <perl...@rjbs.manxome.org> [2012-09-12 03:25]:
> * Aristotle Pagaltzis <paga...@gmx.de> [2012-09-11T21:11:27]
> > Heretical question: what makes an experimental feature anything else
> > than a regular feature that isn’t included in any version bundle?
> > I.e. why not just have the user write `use feature 'lexical_subs'`
> > explicitly in 5.18 to get it, but withhold it if they write just
> > `use 5.018`? Then if the experiment works out, it becomes part of
> > the 5.20 or 5.22 feature bundle, so `use 5.022` enables it by
> > default.
>
> I think this is very very close to what is actually proposed, with the
> small change that we force you to write "experimental" in there, while
> it's still experimental, as a sign of acknowledgement that you know
> it's experimental.

Why do we want that? Should we want that?

I also submit the following for consideration:

no warnings 'experimental_lexical_subs';
use feature 'lexical_subs'; # would warn on import

Jesse Luehrs

unread,
Sep 11, 2012, 10:40:20 PM9/11/12
to perl5-...@perl.org
On Wed, Sep 12, 2012 at 03:40:35AM +0200, Aristotle Pagaltzis wrote:
> * Ricardo Signes <perl...@rjbs.manxome.org> [2012-09-12 03:25]:
> > * Aristotle Pagaltzis <paga...@gmx.de> [2012-09-11T21:11:27]
> > > Heretical question: what makes an experimental feature anything else
> > > than a regular feature that isn’t included in any version bundle?
> > > I.e. why not just have the user write `use feature 'lexical_subs'`
> > > explicitly in 5.18 to get it, but withhold it if they write just
> > > `use 5.018`? Then if the experiment works out, it becomes part of
> > > the 5.20 or 5.22 feature bundle, so `use 5.022` enables it by
> > > default.
> >
> > I think this is very very close to what is actually proposed, with the
> > small change that we force you to write "experimental" in there, while
> > it's still experimental, as a sign of acknowledgement that you know
> > it's experimental.
>
> Why do we want that? Should we want that?

We do want *something* that will force people to see that something is
experimental, or else we're back to our current state of "well, the docs
say it's experimental, but everybody is using it already because nobody
reads the docs, so we can't change it", which, as has been pointed out,
isn't really very experimental at all.

> I also submit the following for consideration:
>
> no warnings 'experimental_lexical_subs';
> use feature 'lexical_subs'; # would warn on import

This would also be a reasonable alternative.

-doy

Aristotle Pagaltzis

unread,
Sep 12, 2012, 12:01:29 AM9/12/12
to perl5-...@perl.org
* Jesse Luehrs <d...@tozt.net> [2012-09-12 04:45]:
> We do want *something* that will force people to see that something is
> experimental, or else we're back to our current state of "well, the
> docs say it's experimental, but everybody is using it already because
> nobody reads the docs, so we can't change it", which, as has been
> pointed out, isn't really very experimental at all.

You’re right.

> > I also submit the following for consideration:
> >
> > no warnings 'experimental_lexical_subs';
> > use feature 'lexical_subs'; # would warn on import
>
> This would also be a reasonable alternative.

I think in that case this is actually better. It doesn’t introduce any
new user-facing concepts, and at the same time is noisier in several
senses. Moving a feature from experimental to supported while supporting
code that used it as experimental would also not require any special
steps, it falls right out of the design.

Steffen Mueller

unread,
Sep 12, 2012, 1:56:30 AM9/12/12
to perl5-...@perl.org
On 09/12/2012 03:11 AM, Aristotle Pagaltzis wrote:
> Heretical question: what makes an experimental feature anything else
> than a regular feature that isn’t included in any version bundle? I.e.
> why not just have the user write `use feature 'lexical_subs'` explicitly
> in 5.18 to get it, but withhold it if they write just `use 5.018`? Then
> if the experiment works out, it becomes part of the 5.20 or 5.22 feature
> bundle, so `use 5.022` enables it by default.
>
> With one fell swoop, forward compat is taken care of.
>
> Tell me what I’m missing.

Documentation value of somebody going "use experimental".

Not saying it's worth it, just adding a data point.

--Steffen

demerphq

unread,
Sep 12, 2012, 2:08:56 AM9/12/12
to Steffen Mueller, perl5-...@perl.org
When people go experimental they usually go postal soon after. :-)

yves

Johan Vromans

unread,
Sep 12, 2012, 2:19:25 AM9/12/12
to perl5-...@perl.org
Aristotle Pagaltzis <paga...@gmx.de> writes:

> Heretical question: what makes an experimental feature anything else
> than a regular feature that isn’t included in any version bundle?

It can be withdrawn without further notice in a subsequent version.

-- Johan

Salvador Fandino

unread,
Sep 12, 2012, 3:39:30 AM9/12/12
to perl5-...@perl.org
But them, if there is some incompatible change on the experimental
feature, it may go unnoticed until it manifests as a bug on the user
program.

There will be no warning telling the user that things have changed, nor
way for perl to know the user wants the behaviour/semantics for, say,
version 0.24.

I would rather allow to use some kind of versioning as any of...

use experimental 'lexical_subs_1';
use experimental lexical_subs => 1;
use experimental lexical_subs => 0.24;

If p5p decides to change the way lexical_subs work between 0.24 and
0.26, they can make code requiring lexical_subs 0.24 fail on 0.26, or
keep support for both versions.

Then, once the feature is considered mature, it can be made activable
from the "feature" package while keeping it also accesible from
"experimental".

BTW, how about using "feature::experimental" instead of "experimental"?




Father Chrysostomos via RT

unread,
Sep 13, 2012, 1:56:31 AM9/13/12
to perl5-...@perl.org, paga...@gmx.de
I think that is the best suggestion so far, but it could do with one
small tweak (s/_.*subs//):

no warnings 'experimental';
use feature 'lexical_subs'; # would warn on import

--

Father Chrysostomos


---
via perlbug: queue: perl5 status: open
https://rt.perl.org:443/rt3/Ticket/Display.html?id=113930

Father Chrysostomos via RT

unread,
Sep 13, 2012, 1:59:45 AM9/13/12
to perl5-...@perl.org
I’m getting black smoke from George Greer’s Windows smoker. Trying to
track it down remotely by tweaking the code and pushing it to a smoke-me
branch multiple times will be very tedious.

Could anyone with access to a functional* Windows machine try and see
which commit on the sprout/lexsub branch caused the first failure?

* I always quantify it that way, since I do have access to a Windows VM,
but with enough strange I/O problems that gcc won’t build perl.

Aristotle Pagaltzis

unread,
Sep 13, 2012, 2:55:54 AM9/13/12
to perl5-...@perl.org
* Father Chrysostomos via RT <perlbug-...@perl.org> [2012-09-13 08:00]:
> I think that is the best suggestion so far, but it could do with one
> small tweak (s/_.*subs//):
>
> no warnings 'experimental';
> use feature 'lexical_subs'; # would warn on import

I imagined `experimental_lexical_subs` a subcategory of `experimental`.

Consider the case of writing code that uses `somefeature`, introduced
in 5.22 experimentally, which turned out to be stable in that release
already, or maybe you know you won’t be running up against the sharp
edges it had at the time. You want to target 5.22 and use the feature.
Easy:


use 5.022;
no warnings 'experimental'; # which ones???
use feature 'somefeature';

But what the 2nd line does may differ on 5.22, 5.24, 5.26 and 5.28. And
you aren’t actively uninterested in other experimental features; you
just want to use the one you know was labelled experimental but worked
fine (/for your current project). Then you really do want to write this:

use 5.022;
no warnings 'experimental_somefeature';
use feature 'somefeature';

There are two alternatives to this. One is repetition:

use 5.022;
no warnings 'experimental';
use feature 'somefeature';
use warnings 'experimental';

That way, only the warning against a particular experimental feature is
silenced. Repetition is unavoidable since trying to limit the scope of
the no-warnings also limits the scope of the feature:

use 5.022;
{ no warnings 'experimental';
use feature 'somefeature'; }
# no somefeature here :-(

The other option is to make the `experimental` category magical in that
it gets some logic that checks the `use 5.XXX` in scope and pins the set
of experimental features that `no warnings` turns off to the set of that
version of perl.

But magic bad.

For one it’s simply complicated to understand even the basic DWIM goal.
Second, it loses the advantage of the warnings-based design that forward
compat is free: now a set of version mapping rules has to be maintained
somewhere off to a side, and touched every time a feature is upgraded
from experimental to stable. Third, and most damning, the semantics of
*enabling* the `experimental` warnings category have suddenly turned
*really* bizarre. (Just try to reason it a bit.)

Bottom line, I think it’s best to just let the `experimental` category’s
meaning vary over versions, and provide individual categories for each
of the features. In short throw-away scripts, the convenience of turning
off the whole category is useful. For more serious work, there should be
more fine-grained and stable categories.

Aristotle Pagaltzis

unread,
Sep 13, 2012, 3:05:04 AM9/13/12
to perl5-...@perl.org
* Aristotle Pagaltzis <paga...@gmx.de> [2012-09-13 09:00]:
> use 5.022;
> no warnings 'experimental'; # which ones???
> use feature 'somefeature';
>
> But what the 2nd line does may differ on 5.22, 5.24, 5.26 and 5.28. And
> you aren’t actively uninterested in other experimental features; you
^^^^^^^^^^ correction: you are

Steve Hay

unread,
Sep 13, 2012, 4:48:58 AM9/13/12
to perlbug-...@perl.org, perl5-...@perl.org
Father Chrysostomos via RT wrote on 2012-09-13:
> I’m getting black smoke from George Greer’s Windows smoker. Trying to
> track it down remotely by tweaking the code and pushing it to a smoke-
> me branch multiple times will be very tedious.
>
> Could anyone with access to a functional* Windows machine try and see
> which commit on the sprout/lexsub branch caused the first failure?
>

I got it down to being somewhere between c2837f2b837d7e5c275a691d8c16fef000cc86b7 (passes all op/*.t tests at least) and efece7a52991d97ffbb1eacc44736d04c5847ee2 (fails loads of op/*.t tests). I'll continue bisecting some more later.

Aristotle Pagaltzis

unread,
Sep 13, 2012, 10:25:13 AM9/13/12
to perl5-...@perl.org
* Ricardo Signes <perl...@rjbs.manxome.org> [2012-09-13 15:50]:
> (Side note: experimental_lexical_subs or experimental::lexical_subs?
> I don't think we have any precedent for :: in warning categories.)

Yes, that passed my mind. I dithered for a bit; where does the impulse
come from, would the :: gain us anything? Does it even work, would it
collide with anything?

Turns out we do have a mild precedent in that users are encouraged to
register custom warnings categories based on package names. Core owns
the lower-case no-separator category names. So there is a very minor
pressure against the use of ::, though not in practical terms (it seems
unlikely at best that some user has an experimental::lexical_subs module
and that that registers custom warnings), only in terms of some sort of
convention.

Finally I decided to pass on it because try as I might, I could think of
no benefit of :: over the underscore, and so it seems merely gratuitous.
If anyone can suggest a benefit, please do. In absence of any, it seems
preferable to me to stay within existing conventions.

Aristotle Pagaltzis

unread,
Sep 13, 2012, 10:58:14 AM9/13/12
to perl5-...@perl.org
* Salvador Fandino <sfan...@yahoo.com> [2012-09-12 09:40]:
> On 09/12/2012 06:01 AM, Aristotle Pagaltzis wrote:
>>>> I also submit the following for consideration:
>>>>
>>>> no warnings 'experimental_lexical_subs';
>>>> use feature 'lexical_subs'; # would warn on import
>>
>> I think in that case this is actually better. It doesn’t introduce
>> any new user-facing concepts, and at the same time is noisier in
>> several senses. Moving a feature from experimental to supported while
>> supporting code that used it as experimental would also not require
>> any special steps, it falls right out of the design.
>
> But them, if there is some incompatible change on the experimental
> feature, it may go unnoticed until it manifests as a bug on the user
> program.
>
> There will be no warning telling the user that things have changed, nor
> way for perl to know the user wants the behaviour/semantics for, say,
> version 0.24.
>
> I would rather allow to use some kind of versioning as any of...
>
> use experimental 'lexical_subs_1';
> use experimental lexical_subs => 1;
> use experimental lexical_subs => 0.24;

The issue concerns me too… but I don’t know if versioning even works.
Which changes would have to be declared as a different version? Where is
the line where bug fixes end and redesigns start? If it *is* a redesign,
would not the right approach be simply to rename the feature? (Which
implies that some thought has to be given to names from the beginning,
obviously, to not name features over-broadly right away.)

My experience has generally been that namespaces are a far saner way to
manage the evolution of interfaces than versions – that versioning
causes a lot of complicated semantic problems that simply disappear when
managing change with namespaces instead. At this point I get faintly
queasy whenever versioning of interfaces and protocols comes up – more
often than not it is evil.

> If p5p decides to change the way lexical_subs work between 0.24 and
> 0.26, they can make code requiring lexical_subs 0.24 fail on 0.26, or
> keep support for both versions.

Isn’t trying to support multiple versions of the same feature within the
same interpreter a sure way into madness, though? If several different
versions of the same feature are used within in different scopes of the
same program, how do they all interact? How does one keep a lid on the
potential combinatorial explosion there? (A problem with stable features
already.) I really don’t want to go there. Particularly not on p5p,
where resources are in perpetually short supply.

What’s more, what is the point of *experimental* features if support for
their semantics still has to be retained? Wasn’t the whole point to keep
people from using them at scale too early, to keep these features from
ossifying too quickly? As long as the promise-threat of experimental
features changing or disappearing or else going stable within reasonable
time scales is upheld, isn’t it reasonable to tell people that the price
for using experimental features in production is that they have to test
their code extra carefully when they upgrade their perl? (Of course if
as in the past features are added as experimental and then stay that way
forever, you have no grounds to scold people for using them.)

So my gut feel is, try without versions for a while and see if there are
problems – in particular, problems that cannot be solved with coining
a new name for the new version of the feature. If so, then let’s weigh
the options at that time.

Leon Timmermans

unread,
Sep 13, 2012, 11:13:16 AM9/13/12
to Ricardo Signes, perl5-...@perl.org
On Thu, Sep 13, 2012 at 3:47 PM, Ricardo Signes
<perl...@rjbs.manxome.org> wrote:
> I prefer the more explicit experimental_lexical_subs, for the reasons Aristotle
> provided. I think it's vital to have per-feature categories. (Side note:
> experimental_lexical_subs or experimental::lexical_subs? I don't think we have
> any precedent for :: in warning categories.)
>
> I also like that we can (in some cases) choose to add the experimental warnings
> to *new* versions of perl for *old* experimental features. no warnings
> 'experimental_autoderef' or whatever. (First one that came to mind.)

I'd strongly prefer experimental::lexical_subs over
experimental_lexical_subs; the latter doesn't separate the status from
the actual name of the feature.

Leon

Father Chrysostomos via RT

unread,
Sep 13, 2012, 11:50:23 AM9/13/12
to perl5-...@perl.org, paga...@gmx.de
On Thu Sep 13 07:25:52 2012, aristotle wrote:
> Finally I decided to pass on it because try as I might, I could think of
> no benefit of :: over the underscore, and so it seems merely gratuitous.
> If anyone can suggest a benefit, please do. In absence of any, it seems
> preferable to me to stay within existing conventions.

Existing conventions are to use only a-z.

Eirik Berg Hanssen

unread,
Sep 13, 2012, 11:52:16 AM9/13/12
to Leon Timmermans, Ricardo Signes, perl5-...@perl.org
On Thu, Sep 13, 2012 at 5:13 PM, Leon Timmermans <faw...@gmail.com> wrote:
I'd strongly prefer experimental::lexical_subs over
experimental_lexical_subs; the latter doesn't separate the status from
the actual name of the feature.

  As long as we're shedding bikes: How about "experimental:lexical_subs"?

  ... it's not as if it's a symbol, after all ...


Eirik, briefly considering "experimantal: lexical subs" and "experimental:lexical-subs" ...

Steve Hay

unread,
Sep 13, 2012, 12:59:09 PM9/13/12
to Steve Hay, perlbug-...@perl.org, perl5-...@perl.org
Commit 56e168315961440f9bd040fc9a6b32e128fa289b passes all tests.
The next commit, e630ae0c3e7bb47b642a8e758beadd6cc68404f9, fails lots of tests.


Aristotle Pagaltzis

unread,
Sep 13, 2012, 5:10:24 PM9/13/12
to perl5-...@perl.org
* Father Chrysostomos via RT <perlbug-...@perl.org> [2012-09-13 17:55]:
> On Thu Sep 13 07:25:52 2012, aristotle wrote:
> > Finally I decided to pass on it because try as I might, I could
> > think of no benefit of :: over the underscore, and so it seems
> > merely gratuitous. If anyone can suggest a benefit, please do. In
> > absence of any, it seems preferable to me to stay within existing
> > conventions.
>
> Existing conventions are to use only a-z.

Hmm, point. Clearly I should have paid more attention.

And there is certainly no way to do it without underscores and without
a way of delimiting the `experimental` prefix from the feature name. So
any choice will break convention at least a little, so maybe it doesn’t
make an appreciable difference. I guess using just underscore still has
an argument in its favour in that it is the least break possible… but
I dunno if that convinces me.

Father Chrysostomos via RT

unread,
Sep 13, 2012, 5:29:45 PM9/13/12
to perl5-...@perl.org, Stev...@verosoftware.com
Thank you. Attached is that commit. I cannot see anything in there
that would be platform-specific. Whenever it is convenient for you, do
you think you could try to reduce one of the .t files to a single test?
Maybe it will set off a lightbulb when I see it.
open_ILEO5sOg.txt

Father Chrysostomos via RT

unread,
Sep 13, 2012, 5:43:58 PM9/13/12
to perl5-...@perl.org, paga...@gmx.de, Eirik-Ber...@allverden.no, perl...@rjbs.manxome.org
Porting/todo.pod says this:

=head2 enable lexical enabling/disabling of individual warnings

Currently, warnings can only be enabled or disabled by category. There
are times when it would be useful to quash a single warning, not a
whole category.

And Eirik Berg Hanssen says:
> As long as we're shedding bikes: How about
> "experimental:lexical_subs"?

Now consider that you are proposing a warnings ‘category’ with one
single warning it it.

If you put two and two together, you end up with όλα από πέντε (sorry,
couldn’t resist :-):

use warnings "experimental"; # whole category
use warnings "experimental:lexical_subs"; # single warning

no warnings 'utf8'; # turn them off
use warnings FATAL => 'utf8:wide'; # but I still want this one

And that solves the problem of trying to decide what convention to use
when assigning IDs to warnings. Just come up with something alphabetic,
short, and hence memorable.

Now we don’t have to do it all at once, but we can start with the
experimental category.

Experimental warning IDs should match the feature names, too, so they
can be exempt from the no-underscores rule. But generally the perl core
avoids underscores between letters (CLONE_SKIP being one egregious
example of the violation of that principle), so that user code can use
them safely everywhere.

Aristotle Pagaltzis

unread,
Sep 13, 2012, 6:10:41 PM9/13/12
to perl5-...@perl.org
* Father Chrysostomos via RT <perlbug-...@perl.org> [2012-09-13 23:44]:
> Now consider that you are proposing a warnings ‘category’ with one
> single warning it it.
>
> If you put two and two together, you end up with όλα από πέντε (sorry,
> couldn’t resist :-):

:-)

> use warnings "experimental"; # whole category
> use warnings "experimental:lexical_subs"; # single warning
>
> no warnings 'utf8'; # turn them off
> use warnings FATAL => 'utf8:wide'; # but I still want this one
>
> And that solves the problem of trying to decide what convention to use
> when assigning IDs to warnings. Just come up with something alphabetic,
> short, and hence memorable.

Now *that* I like.

> Now we don’t have to do it all at once, but we can start with the
> experimental category.

Yes, it would require going through all of core and naming every single
warning, right? I was going to say it seems a problem for the lexical
subs work to have to block on that but you’re right, it needn’t be done
all or nothing.

> Experimental warning IDs should match the feature names, too, so they
> can be exempt from the no-underscores rule. But generally the perl
> core avoids underscores between letters (CLONE_SKIP being one
> egregious example of the violation of that principle), so that user
> code can use them safely everywhere.

Yeah. The proposal feels like a unification on the right level that
makes all the answers for the original problems fall out naturally so
I like it rather a lot.

While the approach feels very right though, I feel I can’t ask good
questions about specific designs for it off the cuff/just yet. Is the
colon separating category + ID the right choice? I don’t know. I’d
love to hear if anything occurs to RJBS in particular after letting
it simmer for a while, or anyone.

Father Chrysostomos via RT

unread,
Sep 13, 2012, 8:58:31 PM9/13/12
to perl5-...@perl.org, paga...@gmx.de
On Thu Sep 13 15:11:14 2012, aristotle wrote:
> * Father Chrysostomos via RT <perlbug-...@perl.org> [2012-09-13
23:44]:
> > use warnings "experimental"; # whole category
> > use warnings "experimental:lexical_subs"; # single warning
> >
> > no warnings 'utf8'; # turn them off
> > use warnings FATAL => 'utf8:wide'; # but I still want this one
> >
> > And that solves the problem of trying to decide what convention to use
> > when assigning IDs to warnings. Just come up with something alphabetic,
> > short, and hence memorable.
>
> Now *that* I like.
>

> While the approach feels very right though, I feel I can’t ask good
> questions about specific designs for it off the cuff/just yet. Is the
> colon separating category + ID the right choice? I don’t know. I’d
> love to hear if anything occurs to RJBS in particular after letting
> it simmer for a while, or anyone.

One problem is that warnings might change categories. One instance I
can think of is ‘vector argument not supported with alpha versions’.
Right now it’s in the internal category, believe it or not. That is
completely wrong, and I have already changed it locally to the printf
category.

I think those will be rare, though. We can make backward-compatibility
aliases if necessary (internal:valpha maps to printf:valpha and is
unrelated to the internal category).

David Mertens

unread,
Sep 13, 2012, 11:42:17 PM9/13/12
to perlbug-...@perl.org, paga...@gmx.de, perl5-...@perl.org

What's the reason for using one instead of two colons? Perl namespace encoding suggests two, but Huffman encoding suggests one.

Or should this question be tagged as bike shedding and ignored for the moment?

David

Aristotle Pagaltzis

unread,
Sep 14, 2012, 12:44:45 AM9/14/12
to perl5-...@perl.org
* David Mertens <dcmerte...@gmail.com> [2012-09-14 05:45]:
> What's the reason for using one instead of two colons? Perl namespace
> encoding suggests two, but Huffman encoding suggests one.
>
> Or should this question be tagged as bike shedding and ignored for the
> moment?

Since it’s FC who came up with the approach, maybe it should be

use warnings "internal'valpha";

in his honour. ;-)

Father Chrysostomos via RT

unread,
Sep 14, 2012, 1:14:38 AM9/14/12
to perl5-...@perl.org, dcmerte...@gmail.com
On Thu Sep 13 20:42:56 2012, dcmerte...@gmail.com wrote:
> What's the reason for using one instead of two colons? Perl namespace
> encoding suggests two, but Huffman encoding suggests one.

Warnings categories are not packages. I could equally argue that
"experimental->{lexical_subs}" should be used. :-)

I think the single colon prevents anyone from drawing connections where
there are none.

But we could use anything.

Father Chrysostomos via RT

unread,
Sep 14, 2012, 1:43:24 AM9/14/12
to perl5-...@perl.org, paga...@gmx.de
On Thu Sep 13 08:50:22 2012, sprout wrote:
> On Thu Sep 13 07:25:52 2012, aristotle wrote:
> > Finally I decided to pass on it because try as I might, I could think of
> > no benefit of :: over the underscore, and so it seems merely gratuitous.
> > If anyone can suggest a benefit, please do. In absence of any, it seems
> > preferable to me to stay within existing conventions.
>
> Existing conventions are to use only a-z.

I take that back. We already have non_unicode. But why non_unicode and
nonchar have to follow different conventions is beyond me.

Eirik Berg Hanssen

unread,
Sep 14, 2012, 2:40:34 AM9/14/12
to perlbug-...@perl.org, perl5-...@perl.org, dcmerte...@gmail.com
On Fri, Sep 14, 2012 at 7:14 AM, Father Chrysostomos via RT <perlbug-...@perl.org> wrote:
I think the single colon prevents anyone from drawing connections where
there are none.

  That was the idea.  Or rather, no Perl-related connections.  Colons are used elsewhere for similar purposes – with URI schemes and MediaWiki namespaces, to name the two first on my mind.  So, while alien to Perl proper (and thus not misleading), it might still be familiar to users, and so easier to remember than some arbitrary separator. :)


Eirik

Father Chrysostomos via RT

unread,
Sep 14, 2012, 7:30:44 PM9/14/12
to perl5-...@perl.org, Stev...@verosoftware.com, rev....@gmail.com
On Thu Sep 13 14:29:45 2012, sprout wrote:
> On Thu Sep 13 09:59:45 2012, Stev...@verosoftware.com wrote:
> > Steve Hay wrote on 2012-09-13:
> > Commit 56e168315961440f9bd040fc9a6b32e128fa289b passes all tests.
> > The
> > next commit, e630ae0c3e7bb47b642a8e758beadd6cc68404f9, fails lots of
> > tests.
>
> Thank you. Attached is that commit. I cannot see anything in there
> that would be platform-specific. Whenever it is convenient for you, do
> you think you could try to reduce one of the .t files to a single test?
> Maybe it will set off a lightbulb when I see it.

Chip sent me a configuration with which I was able to reproduce the
failures on Mac OS X. So I can take over from here. Thank you for your
help so far.

Father Chrysostomos via RT

unread,
Sep 15, 2012, 8:46:38 AM9/15/12
to perl5-...@perl.org, Stev...@verosoftware.com, rev....@gmail.com
On Fri Sep 14 16:30:44 2012, sprout wrote:
> On Thu Sep 13 14:29:45 2012, sprout wrote:
> > On Thu Sep 13 09:59:45 2012, Stev...@verosoftware.com wrote:
> > > Steve Hay wrote on 2012-09-13:
> > > Commit 56e168315961440f9bd040fc9a6b32e128fa289b passes all tests.
> > > The
> > > next commit, e630ae0c3e7bb47b642a8e758beadd6cc68404f9, fails lots of
> > > tests.
> >
> > Thank you. Attached is that commit. I cannot see anything in there
> > that would be platform-specific. Whenever it is convenient for you, do
> > you think you could try to reduce one of the .t files to a single test?
> > Maybe it will set off a lightbulb when I see it.
>
> Chip sent me a configuration with which I was able to reproduce the
> failures on Mac OS X. So I can take over from here. Thank you for your
> help so far.

It was an uninitialized C auto. I have squashed this diff with the
offending commit and pushed to perl.git again.

diff --git a/toke.c b/toke.c
index 47c2b0a..db08ee7 100644
--- a/toke.c
+++ b/toke.c
@@ -6779,6 +6779,7 @@ Perl_yylex(pTHX)
rv2cv_op = NULL;
orig_keyword = 0;
lex = 0;
+ off = 0;
}
just_a_word: {
int pkgname = 0;

Father Chrysostomos via RT

unread,
Sep 16, 2012, 2:41:22 AM9/16/12
to perl5-...@perl.org, paga...@gmx.de
On Thu Sep 13 15:11:14 2012, aristotle wrote:
It’s in now as 74760be3f6. Did I perhaps act too soon? I don’t know.
I’ll see if my commit bit get revoked. :-)

Aristotle Pagaltzis

unread,
Sep 16, 2012, 3:33:19 AM9/16/12
to perl5-...@perl.org
* Father Chrysostomos via RT <perlbug-...@perl.org> [2012-09-16 08:45]:
> It’s in now as 74760be3f6. Did I perhaps act too soon? I don’t know.
> I’ll see if my commit bit get revoked. :-)

Ah, design by fait accompli. :-)

Well, let’s see. I don’t *expect* any surprises from this one. But then
what is a surprise if you expect it?

Nicholas Clark

unread,
Sep 17, 2012, 6:37:13 AM9/17/12
to Father Chrysostomos via RT, perl5-...@perl.org, da...@iabyn.com
Sorry, this never got answered at the time, partly because I saw that you
seemed to have answered it yourself within 24 hours

On Fri, Aug 03, 2012 at 11:21:05PM -0700, Father Chrysostomos via RT wrote:

> commit adf8f095c5881bcedf07b8e41072f8125e00b5a6
> Author: Nicholas Clark <ni...@ccl4.org>
> Date: Fri Feb 26 09:18:44 2010 +0000
>
> Set PADSTALE on all lexicals at the end of sub creation.
>
> The PADSTALEness of lexicals between the 0th and 1st call to a
> subroutine is now
> consistent with the state between the nth and (n + 1)th call.
>
> This permits a work around in Perl_padlist_dup() to avoid leaking
> active pad
> data into a new thread, whilst still correctly bodging the external
> references
> needed by the current ?{} implementation. Fix that, and this can be
> removed.
>
>
> I don't know whether this affects my subs yet, but I would like to gain
> a better understanding of this commit. How did ?{} blocks work before?
> What exactly was the fix intended to do?

I can't remember better than the commit message says.

?{} blocks before and after this commit continued to be a complete
hack. (This was before Dave's fix for them landed). The short description is
"lexicals in ?{} blocks didn't work." Sadly, they *seemed* to work, until
you tried to do anything more exciting than calling a subroutine once.

On Sat, Aug 04, 2012 at 06:03:27PM -0700, Father Chrysostomos via RT wrote:
> On Sat Aug 04 06:43:00 2012, sprout wrote:

> > I can reproduce this bug even further back:
> >
> > sub foo {
> > my $x if @_;
> > return if @_;
> >
> > $x = 17;
> > print $x, "\n";
> > print sub { $x }->(), "\n";
> > return;
> >
> > }
> > foo(1); # make $x stale in all perl versions
> > foo;

This doesn't surprise me. That commit revealed at least one test failure
from the BBC, but I was able to write a different test case for that module
which failed in the same way with perl before the commit you quote.

> > $ pbpaste|perl5.10.1 -w
> > 17
> > Variable "$x" is not available at - line 7.
> > Use of uninitialized value in print at - line 7.
> >
> > $ pbpaste|perl5.10.0 -w
> > 17
> > 17
> >
>
> I've fixed both those issues with commit cae5dbbe3.

Good stuff.

Nicholas Clark

Nicholas Clark

unread,
Sep 17, 2012, 6:38:57 AM9/17/12
to Father Chrysostomos via RT, perl5-...@perl.org
On Thu, Aug 23, 2012 at 09:40:57AM -0700, Father Chrysostomos via RT wrote:

> Just for future reference: I have found that I do still need two
> separate ops for introcv and clonecv.

[snip detailed explanation]

Very useful. Thanks for taking the time to write a coherent explanation.

Is this in a comment in the code anywhere? I think it's more appropriate to
put it somewhere in the repository, as that's much more easily findable in
the future.

Nicholas Clark

Father Chrysostomos via RT

unread,
Sep 17, 2012, 9:31:15 AM9/17/12
to perl5-...@perl.org, ni...@ccl4.org
Yes, it’s in op.c:block_end.

I meant to say that, but I apparently never finished writing the message
you cite. But at least it is understandable. :-)

--

Father Chrysostomos


---
via perlbug: queue: perl5 status: resolved
https://rt.perl.org:443/rt3/Ticket/Display.html?id=113930

Father Chrysostomos via RT

unread,
Sep 25, 2012, 9:05:13 PM9/25/12
to perl5-...@perl.org, perl...@rjbs.manxome.org
On Thu Sep 20 21:25:09 2012, perl...@rjbs.manxome.org wrote:
> * Father Chrysostomos via RT <perlbug-...@perl.org> [2012-09-
> 13T17:43:58]
> > use warnings "experimental"; # whole category
> > use warnings "experimental:lexical_subs"; # single warning
>
> I like the idea, but not enough. I think it will seem pretty good
> until it
> seems bad.
>
> I think we should do two things.
>
> 1) these warnings should use ::, as if we're registering them as part
> of an
> 'experimental' namespace. Introducing ":" as a separator for
> something that
> looks like a package/module, and sometimes is (use warnings
> 'File::Find') is
> just asking for confusion.

Should I also remove the documentation about extending : to individual
warnings?

>
> 2) we should ensure that the mechanism for identifying core exceptions
> works on
> core warnings as well; or, in other terms: we want to solve this
> problem
> for core exceptions, and a core warning is just an exception with
> no teeth
>
> I know chromatic, at least, is working on this problem. I'll drop him
> a line
> in the morning, unless he reads this and replies first.
>


--

Father Chrysostomos

Father Chrysostomos via RT

unread,
Sep 30, 2012, 3:09:58 AM9/30/12
to perl5-...@perl.org
On Wed Sep 26 16:12:38 2012, perl...@rjbs.manxome.org wrote:
> * Father Chrysostomos via RT <perlbug...@perl.org> [2012-09-
> 25T21:05:13]
> > Should I also remove the documentation about extending : to
> individual
> > warnings?
>
> Please. Sorry for the delay.

Now done in commit f1d34ca8c42d.

--

Father Chrysostomos

0 new messages