Perl / perl5

🐪 The Perl programming language
https://dev.perl.org/perl5/
Other
1.85k stars 527 forks source link

"return" required in some anonymous closures #6853

Closed p5pRT closed 10 years ago

p5pRT commented 20 years ago

Migrated from rt.perl.org#24250 (status was 'open')

Searchable as RT24250$

p5pRT commented 20 years ago

From martin@suttles.sca.sfbay.sun.com

Created by martin@suttles.sca.sfbay.sun.com

Consider the following perl program

my $count = 0; my $x = [sub() { $count }\,   sub() { return $count }\,   sub($) { $count += $_[0] }]; $x->[2](3); printf "%d %d\n"\, $x->[0]()\, $x->[1]();

This prints 0 3 when it should print 3 3

The two anonymous subs $x->[0] and $x->[1] should have exactly the same effect because `return' is supposed to be redundant when returning the last expression in a sub.

Perl Info ``` Flags: category=core severity=high Site configuration information for perl v5.8.1: Configured by martin at Sun Oct 19 13:47:11 PDT 2003. Summary of my perl5 (revision 5.0 version 8 subversion 1) configuration: Platform: osname=solaris, osvers=2.9, archname=sun4-solaris uname='sunos suttles 5.9 generic_112233-05 sun4u sparc sunw,sun-blade-1000 ' config_args='-ds -e -Dprefix=/usr/local' hint=recommended, useposix=true, d_sigaction=define usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef useperlio=define d_sfio=undef uselargefiles=define usesocks=undef use64bitint=undef use64bitall=undef uselongdouble=undef usemymalloc=n, bincompat5005=undef Compiler: cc='cc', ccflags ='-I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64', optimize='-O', cppflags='-I/usr/local/include' ccversion='Sun C 5.5 2003/03/12', gccversion='', gccosandvers='' intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=4321 d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16 ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8 alignbytes=8, prototype=define Linker and Libraries: ld='cc', ldflags =' -L/usr/lib -L/usr/ccs/lib -L/u/SUNWspro/prod/lib -L/usr/local/lib ' libpth=/usr/lib /usr/ccs/lib /u/SUNWspro/prod/lib /usr/local/lib libs=-lsocket -lnsl -ldl -lm -lc perllibs=-lsocket -lnsl -ldl -lm -lc libc=/lib/libc.so, so=so, useshrplib=false, libperl=libperl.a gnulibc_version='' Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags=' -z ignore -z lazyload -z combreloc' cccdlflags='-KPIC', lddlflags=' -G -z ignore -z lazyload -z combreloc -L/usr/lib -L/usr/ccs/lib -L/u/SUNWspro/prod/lib -L/usr/local/lib' Locally applied patches: @INC for perl v5.8.1: /usr/local/lib/perl5/5.8.1/sun4-solaris /usr/local/lib/perl5/5.8.1 /usr/local/lib/perl5/site_perl/5.8.1/sun4-solaris /usr/local/lib/perl5/site_perl/5.8.1 /usr/local/lib/perl5/site_perl/5.8.0/sun4-solaris /usr/local/lib/perl5/site_perl/5.8.0 /usr/local/lib/perl5/site_perl . Environment for perl v5.8.1: HOME=/u/martin LANG (unset) LANGUAGE (unset) LD_LIBRARY_PATH (unset) LOGDIR (unset) PATH=/u/martin/bin:/u/martin/bin/sun:/usr/java1.4.2/bin:/java/devtools/sparc/bin:/usr/local/bin:/usr/local/samba/bin:/usr/sfw/bin:/opt/sfw/bin:/usr/dt/bin:/usr/openwin/bin:/usr/xpg4/bin:/usr/proc/bin:/usr/ccs/bin:/usr/bin:/sbin:/usr/sbin:/java/devtools/sparc/gnucc/bin:/u/SUNWspro/bin:. PERL_BADLANG (unset) SHELL=/usr/bin/zsh ```
p5pRT commented 20 years ago

From @lizmat

At 23​:01 +0000 10/19/03\, martin@​suttles.sca.sfbay.sun.com (via RT) wrote​:

# New Ticket Created by martin@​suttles.sca.sfbay.sun.com # Please include the string​: [perl #24250] # in the subject line of all future correspondence about this issue. # \<URL​: http​://rt.perl.org/rt2/Ticket/Display.html?id=24250 >

This is a bug report for perl from martin@​suttles.sca.sfbay.sun.com\, generated with the help of perlbug 1.34 running under perl v5.8.1.

----------------------------------------------------------------- [Please enter your report here] Consider the following perl program

my $count = 0; my $x = [sub() { $count }\, sub() { return $count }\, sub($) { $count += $_[0] }]; $x->[2](3); printf "%d %d\n"\, $x->[0]()\, $x->[1]();

This prints 0 3 when it should print 3 3

Confirmed.

Please note that if you change​:

  my $count = 0;

to​:

  our $count = 0;

the result as is expected. So this would imply a lexical pad problem to me.

Furthermore\, if you change​:

  my $count = 0;

to​:

  my $count = 'Foo';

the result is _still_​:

0 3

which indicates to me the "0" is gotten from somewhere else\, rather than from $count.

Liz

p5pRT commented 20 years ago

From @lizmat

At 11​:44 +0200 10/20/03\, Elizabeth Mattijsen wrote​:

At 23​:01 +0000 10/19/03\, martin@​suttles.sca.sfbay.sun.com (via RT) wrote​:

my $count = 0; my $x = [sub() { $count }\, sub() { return $count }\, sub($) { $count += $_[0] }]; $x->[2](3); printf "%d %d\n"\, $x->[0]()\, $x->[1]();

This prints 0 3 when it should print 3 3

Hmmm... both of the following return correct results also​:

BEGIN {my $count = 'foo'}; # $foo properly initialized at compile time my $x = [sub() { $count }\,   sub() { return $count }\,   sub($) { $count += $_[0] }]; $x->[2](3); printf "%d %d\n"\, $x->[0]()\, $x->[1]();

my $count = 'foo'; my $x = [sub { $count }\, # removed prototype   sub() { return $count }\,   sub($) { $count += $_[0] }]; $x->[2](3); printf "%d %d\n"\, $x->[0]()\, $x->[1]();

So maybe this is an optimizer related problem as well?

Liz

p5pRT commented 20 years ago

From @lizmat

(I should stop answering my own posts ;-)

At 11​:55 +0200 10/20/03\, Elizabeth Mattijsen wrote​:

Hmmm... both of the following return correct results also​:

The problem can be simplified to the following code​:

my $foo = 'foo'; my $get = sub () {$foo}; my $set = sub ($) {$foo = $_[0]}; $set->('bar'); print "foo = $foo = ".$get->()."\n"; __END__ foo = bar = foo

so this looks like an optimizer problem to me​: the $get sub is referring to something else than the package lexical $foo.

Liz

p5pRT commented 20 years ago

From @iabyn

On Mon\, Oct 20\, 2003 at 12​:17​:24PM +0200\, Elizabeth Mattijsen wrote​:

(I should stop answering my own posts ;-)

At 11​:55 +0200 10/20/03\, Elizabeth Mattijsen wrote​:

Hmmm... both of the following return correct results also​:

The problem can be simplified to the following code​:

my $foo = 'foo'; my $get = sub () {$foo}; my $set = sub ($) {$foo = $_[0]}; $set->('bar'); print "foo = $foo = ".$get->()."\n"; __END__ foo = bar = foo

so this looks like an optimizer problem to me​: the $get sub is referring to something else than the package lexical $foo.

This isn't a bug\, it's a feature :-)

sub () {$lexical} is a constant sub generator\, ie each call to 'sub' returns a new constant sub rather than a closure. It doesn't seem to be well documented though. Been around since 5.8.0.

eg

  my $x;

  for (10\,20) {   $x = $_;   $a0 = sub(){$x};   $a1 = sub(){$x+1};   print $a0->()\, " "\, $a1->()\, "\n";   $x += 1000;   print $a0->()\, " "\, $a1->()\, "\n";   }

outputs

  10 11   10 1011   20 21   20 1021

since $a0 is a constant sub\, but $a1 is a closure.

-- print+qq&$}$"$/$s$\,$*${$}$g$s$@​$.$q$\,$​:$.$q$^$\,$@​$*$~$;$.$q$m&if+map{m\,^\d{0\\,}\,\,${$​::{$'}}=chr($"+=$&||1)}q&10m22\,42}6​:17*2~2.3@​3;^2$g3q/s"&=~m*\d\*.*g

p5pRT commented 20 years ago

From @lizmat

At 11​:45 +0100 10/20/03\, Dave Mitchell wrote​:

On Mon\, Oct 20\, 2003 at 12​:17​:24PM +0200\, Elizabeth Mattijsen wrote​:

(I should stop answering my own posts ;-)

At 11​:55 +0200 10/20/03\, Elizabeth Mattijsen wrote​:

Hmmm... both of the following return correct results also​:

The problem can be simplified to the following code​: so this looks like an optimizer problem to me​: the $get sub is referring to something else than the package lexical $foo. This isn't a bug\, it's a feature :-) sub () {$lexical} is a constant sub generator\, ie each call to 'sub' returns a new constant sub rather than a closure. It doesn't seem to be well documented though. Been around since 5.8.0.

I always thought you would need to document a bug before it becomes a feature? ;-)

Seriously\, I haven't been able to find _any_ documentation on this feature. It definitely is not mentioned in the 5.8.0 perldelta (or it is described without the terms "constant" or "generator").

If this _is_ a new feature of 5.8.0\, maybe it should be at least documented in the 5.8.2 perldelta? And possible somewhere else. Suggestions for locations where this should be documented? I'll write up a description and submit a patch then.

Liz

p5pRT commented 20 years ago

From nick.ing-simmons@elixent.com

Elizabeth Mattijsen \liz@&#8203;dijkmat\.nl writes​:

At 11​:44 +0200 10/20/03\, Elizabeth Mattijsen wrote​:

At 23​:01 +0000 10/19/03\, martin@​suttles.sca.sfbay.sun.com (via RT) wrote​:

my $count = 0; my $x = [sub() { $count }\, sub() { return $count }\, sub($) { $count += $_[0] }]; $x->[2](3); printf "%d %d\n"\, $x->[0]()\, $x->[1]();

This prints 0 3 when it should print 3 3

Hmmm... both of the following return correct results also​:

BEGIN {my $count = 'foo'}; # $foo properly initialized at compile time

No. That has initialized a $count lexical to the BEGIN

my $x = [sub() { $count }\,

No lexical $count in scope here 'tis a global.

     sub\(\) \{ return $count \}\,
     sub\($\) \{ $count \+= $\_\[0\] \}\];

$x->[2](3); printf "%d %d\n"\, $x->[0]()\, $x->[1]();

p5pRT commented 20 years ago

From nick.ing-simmons@elixent.com

Elizabeth Mattijsen \liz@&#8203;dijkmat\.nl writes​:

(I should stop answering my own posts ;-)

At 11​:55 +0200 10/20/03\, Elizabeth Mattijsen wrote​:

Hmmm... both of the following return correct results also​:

The problem can be simplified to the following code​:

my $foo = 'foo'; my $get = sub () {$foo}; my $set = sub ($) {$foo = $_[0]}; $set->('bar'); print "foo = $foo = ".$get->()."\n"; __END__ foo = bar = foo

so this looks like an optimizer problem to me​: the $get sub is referring to something else than the package lexical $foo.

What is a 'package lexical' ?   - things are either in package or lexical never both...

p5pRT commented 20 years ago

From @lizmat

At 13​:32 +0100 10/20/03\, Nick Ing-Simmons wrote​:

Elizabeth Mattijsen \liz@&#8203;dijkmat\.nl writes​:

Hmmm... both of the following return correct results also​: BEGIN {my $count = 'foo'}; # $foo properly initialized at compile time No. That has initialized a $count lexical to the BEGIN

Good point​: I of course meant​:

my $count; BEGIN {$count = 'foo'}

Unfortunately\, I had missed the use of printf() rather than print\, so I also missed the format specification. Had I changed if from %d to %s\, then the test would have told me more (Thanks\, Yves!).

Liz

p5pRT commented 20 years ago

From @lizmat

At 13​:34 +0100 10/20/03\, Nick Ing-Simmons wrote​:

so this looks like an optimizer problem to me​: the $get sub is referring to something else than the package lexical $foo. What is a 'package lexical' ? - things are either in package or lexical never both...

A package lexical is a lexical defined at the package "scope"?

package Foo; my $package_lexical; {   my $not_a_package_lexical; }

I thought that was a pretty well known concept?

Liz

p5pRT commented 20 years ago

From @mjdominus

Dave Mitchell \davem@&#8203;fdgroup\.com​:

This isn't a bug\, it's a feature :-)

sub () {$lexical} is a constant sub generator\, ie each call to 'sub' returns a new constant sub rather than a closure.

Oh well\, so much for the principle of least astonishment.

What's the workaround for this feature?

p5pRT commented 20 years ago

From @demerphq

At 13​:34 +0100 10/20/03\, Nick Ing-Simmons wrote​:

so this looks like an optimizer problem to me​: the $get sub is referring to something else than the package lexical $foo. What is a 'package lexical' ? - things are either in package or lexical never both...

A package lexical is a lexical defined at the package "scope"?

Except that there is no such thing as package scope. There is file scope and block scope\, nothing else.

#!perl -l package foo; my $bar="hello"; print $bar; package main; print $bar;

__END__ hello hello

package Foo; my $package_lexical; { my $not_a_package_lexical; }

I thought that was a pretty well known concept?

Well\, I think its a pretty well known misnomer. But it still is a misnomer. $package_lexical should actually be called $file_lexical.

If you want a "package lexical" youll have to wrap the whole thing in a block.

package foo; {   my $package_foo_lexical; }

or

{   package foo;   my $package_foo_lexical; }

Personally I like the first one more....

Yves

p5pRT commented 20 years ago

From @lizmat

At 08​:58 -0400 10/20/03\, Mark Jason Dominus wrote​:

Dave Mitchell \davem@&#8203;fdgroup\.com​:

This isn't a bug\, it's a feature :-)

sub () {$lexical} is a constant sub generator\, ie each call to 'sub' returns a new constant sub rather than a closure.

Oh well\, so much for the principle of least astonishment.

What's the workaround for this feature?

Dropping the prototype seems to work​:

my $foo = 'foo'; my $get = sub {$foo}; # look\, no prototype! my $set = sub ($) {$foo = $_[0]}; $set->('bar'); print "foo = $foo = ".$get->()."\n"; __END__ foo = bar = bar

Liz

p5pRT commented 20 years ago

From nick.ing-simmons@elixent.com

Elizabeth Mattijsen \liz@&#8203;dijkmat\.nl writes​:

At 13​:34 +0100 10/20/03\, Nick Ing-Simmons wrote​:

so this looks like an optimizer problem to me​: the $get sub is referring to something else than the package lexical $foo. What is a 'package lexical' ? - things are either in package or lexical never both...

A package lexical is a lexical defined at the package "scope"?

package Foo; my $package_lexical; { my $not_a_package_lexical; }

I thought that was a pretty well known concept? Not by me - calling it a package lexical suggests adding a 'package' would make a difference. It doesn't.

package Bar; my $file_lexical;

package Foo; {   package Baz;   my $nested_lexical = $file_lexical; }

p5pRT commented 20 years ago

From @iabyn

On Mon\, Oct 20\, 2003 at 02​:47​:36PM +0200\, Elizabeth Mattijsen wrote​:

At 13​:34 +0100 10/20/03\, Nick Ing-Simmons wrote​:

so this looks like an optimizer problem to me​: the $get sub is referring to something else than the package lexical $foo. What is a 'package lexical' ? - things are either in package or lexical never both...

A package lexical is a lexical defined at the package "scope"?

package Foo; my $package_lexical; { my $not_a_package_lexical; }

No\, $package_lexical is a file-scoped lexical; it has nothing whatsoever to do with packages.

-- In the 70's we wore flares because we didn't know any better. What possible excuse does the current generation have?

p5pRT commented 20 years ago

From @iabyn

On Mon\, Oct 20\, 2003 at 08​:58​:05AM -0400\, Mark Jason Dominus wrote​:

Dave Mitchell \davem@&#8203;fdgroup\.com​:

This isn't a bug\, it's a feature :-)

sub () {$lexical} is a constant sub generator\, ie each call to 'sub' returns a new constant sub rather than a closure.

Oh well\, so much for the principle of least astonishment.

What's the workaround for this feature?

Remove the ()'s.

-- To collect all the latest movies\, simply place an unprotected ftp server on the Internet\, and wait for the disk to fill....

p5pRT commented 20 years ago

From @lizmat

At 13​:59 +0100 10/20/03\, Orton\, Yves wrote​:

At 13​:34 +0100 10/20/03\, Nick Ing-Simmons wrote​:

so this looks like an optimizer problem to me​: the $get sub is referring to something else than the package lexical $foo. What is a 'package lexical' ? - things are either in package or lexical never both...

A package lexical is a lexical defined at the package "scope"? Except that there is no such thing as package scope. There is file scope and block scope\, nothing else.

#!perl -l package foo; my $bar="hello"; print $bar; package main; print $bar;

__END__ hello hello

Or alternately​:

use strict; use warnings;

package Foo; my $foo = 1;

package Bar; my $foo = 2; __END__ "my" variable $foo masks earlier declaration in same scope at line 8.

I see your point.

package Foo; my $package_lexical; { my $not_a_package_lexical; } I thought that was a pretty well known concept? Well\, I think its a pretty well known misnomer. But it still is a misnomer. $package_lexical should actually be called $file_lexical.

If you want a "package lexical" youll have to wrap the whole thing in a block.

package foo; { my $package_foo_lexical; }

or

{ package foo; my $package_foo_lexical; }

Personally I like the first one more....

{   package Foo;   print __PACKAGE__\,$/; } print __PACKAGE__\,$/; __END__ Foo main

See\, packages are scoped! ;-) Just kidding. I will now start to reprogram myself to use "file lexical" rather than "package lexical".

Liz

p5pRT commented 20 years ago

From nick.ing-simmons@elixent.com

Mark Jason Dominus \mjd@&#8203;plover\.com writes​:

Dave Mitchell \davem@&#8203;fdgroup\.com​:

This isn't a bug\, it's a feature :-)

sub () {$lexical} is a constant sub generator\, ie each call to 'sub' returns a new constant sub rather than a closure.

Oh well\, so much for the principle of least astonishment.

What's the workaround for this feature?

A. Don't give the () prototype (they don't do anything useful   on dynamic calls anyway). B. Add a return

p5pRT commented 20 years ago

From nick.ing-simmons@elixent.com

Yves Orton \yves\.orton@&#8203;de\.mci\.com writes​:

A package lexical is a lexical defined at the package "scope"?

Except that there is no such thing as package scope. There is file scope and block scope\, nothing else.

If you want a "package lexical" youll have to wrap the whole thing in a block.

package foo; { my $package_foo_lexical; }

or

{ package foo; my $package_foo_lexical; }

Personally I like the first one more....

And both are surely equivalent to

{ my $invisible_lexical; }

Yves

p5pRT commented 20 years ago

From @demerphq

Except that there is no such thing as package scope. There is file scope and block scope\, nothing else.

Obviously I only meant this at the lexical level...

Personally I like the first one more....

And both are surely equivalent to

{ my $invisible_lexical; }

Well I did assume that more would be inside the block\, such as procedure declarations....

Or did I miss your point?

Yves

p5pRT commented 20 years ago

From @iabyn

On Mon\, Oct 20\, 2003 at 02​:29​:11PM +0200\, Elizabeth Mattijsen wrote​:

At 11​:45 +0100 10/20/03\, Dave Mitchell wrote​:

On Mon\, Oct 20\, 2003 at 12​:17​:24PM +0200\, Elizabeth Mattijsen wrote​:

(I should stop answering my own posts ;-)

At 11​:55 +0200 10/20/03\, Elizabeth Mattijsen wrote​:

Hmmm... both of the following return correct results also​:

The problem can be simplified to the following code​: so this looks like an optimizer problem to me​: the $get sub is referring to something else than the package lexical $foo. This isn't a bug\, it's a feature :-) sub () {$lexical} is a constant sub generator\, ie each call to 'sub' returns a new constant sub rather than a closure. It doesn't seem to be well documented though. Been around since 5.8.0.

I always thought you would need to document a bug before it becomes a feature? ;-)

Seriously\, I haven't been able to find _any_ documentation on this feature. It definitely is not mentioned in the 5.8.0 perldelta (or it is described without the terms "constant" or "generator").

If this _is_ a new feature of 5.8.0\, maybe it should be at least documented in the 5.8.2 perldelta? And possible somewhere else. Suggestions for locations where this should be documented? I'll write up a description and submit a patch then.

I think the best place would be in perlsub.pod in =head2 Constant Functions

Personally I think its a confusing feature\, but it appears to be used in lib/constant.pm - presumably as a cheap way of creating the const subs as needed. C\<use constant foo => 1> gets implemented like   { my ($name\, $val) = @​_; *$name = sub(){$val} }

Anyone feel like deprecating it ;-)

-- Little fly\, thy summer's play my thoughtless hand has terminated with extreme prejudice.   (with apologies to William Blake)

p5pRT commented 20 years ago

From @lizmat

At 14​:57 +0100 10/20/03\, Dave Mitchell wrote​:

On Mon\, Oct 20\, 2003 at 02​:29​:11PM +0200\, Elizabeth Mattijsen wrote​:

Seriously\, I haven't been able to find _any_ documentation on this feature. It definitely is not mentioned in the 5.8.0 perldelta (or it is described without the terms "constant" or "generator").

If this _is_ a new feature of 5.8.0\, maybe it should be at least documented in the 5.8.2 perldelta? And possible somewhere else. Suggestions for locations where this should be documented? I'll write up a description and submit a patch then.

I think the best place would be in perlsub.pod in =head2 Constant Functions

Ok\, I'll do that but first​:

Personally I think its a confusing feature\, but it appears to be used in lib/constant.pm - presumably as a cheap way of creating the const subs as needed. C\<use constant foo => 1> gets implemented like { my ($name\, $val) = @​_; *$name = sub(){$val} } Anyone feel like deprecating it ;-)

Well\, I guess Dominus feels like me\, that it is catching people by surprise.

I think this would call for a compile-time CODE attribute "​: constant"​:

{my ($name\, $val) = @​_; *$name = sub : constant{$val}

Liz

p5pRT commented 20 years ago

From nick.ing-simmons@elixent.com

Yves Orton \yves\.orton@&#8203;de\.mci\.com writes​:

Except that there is no such thing as package scope. There is file scope and block scope\, nothing else.

Obviously I only meant this at the lexical level...

Personally I like the first one more....

And both are surely equivalent to

{ my $invisible_lexical; }

Well I did assume that more would be inside the block\,

Ah - I didn't I took your examples as "boiler plate" to generate a mythical 'package lexical'.

such as procedure declarations....

Or did I miss your point?

No.

Yves

p5pRT commented 20 years ago

From @gbarr

On 20 Oct 2003\, at 13​:29\, Elizabeth Mattijsen wrote​:

At 11​:45 +0100 10/20/03\, Dave Mitchell wrote​:

On Mon\, Oct 20\, 2003 at 12​:17​:24PM +0200\, Elizabeth Mattijsen wrote​:

(I should stop answering my own posts ;-)

At 11​:55 +0200 10/20/03\, Elizabeth Mattijsen wrote​:

Hmmm... both of the following return correct results also​:

The problem can be simplified to the following code​: so this looks like an optimizer problem to me​: the $get sub is referring to something else than the package lexical $foo. This isn't a bug\, it's a feature :-) sub () {$lexical} is a constant sub generator\, ie each call to 'sub' returns a new constant sub rather than a closure. It doesn't seem to be well documented though. Been around since 5.8.0.

It is only supposed to generate a constant sub if there are no other references to the variable. ie there is no way the variable can change.

I always thought you would need to document a bug before it becomes a feature? ;-)

Seriously\, I haven't been able to find _any_ documentation on this feature. It definitely is not mentioned in the 5.8.0 perldelta (or it is described without the terms "constant" or "generator").

Constant subs were in 5.6.0 IIRC

If this _is_ a new feature of 5.8.0\, maybe it should be at least documented in the 5.8.2 perldelta? And possible somewhere else. Suggestions for locations where this should be documented? I'll write up a description and submit a patch then.

I suspect it is a bug in the code that determines if a sub can be considered a constant sub and was introduced during 5.7 development

Graham.

p5pRT commented 20 years ago

From @iabyn

On Mon\, Oct 20\, 2003 at 04​:59​:20PM +0100\, Graham Barr wrote​:

It is only supposed to generate a constant sub if there are no other references to the variable. ie there is no way the variable can change.

But it's easy to create a reference after the event​:

  sub new_constant_sub {   my $val = shift;   my $s = sub() {$val}; # only one ref\, so $s a const sub   $global = \$val; # whoops   $s;   }

I always thought you would need to document a bug before it becomes a feature? ;-)

Seriously\, I haven't been able to find _any_ documentation on this feature. It definitely is not mentioned in the 5.8.0 perldelta (or it is described without the terms "constant" or "generator").

Constant subs were in 5.6.0 IIRC

but anonymous 'const sub generators' were only introduced in 5.8.0\, by

[ 7389] By​: jhi on 2000/10/21 14​:26​:45   Log​: Subject​: Re​: Creating const subs for constants.   From​: John Tobey \jtobey@&#8203;john\-edwin\-tobey\.org   Date​: Fri\, 20 Oct 2000 22​:03​:27 -0400 (EDT)   Message-Id​: \m13mo0N\-000FObC@&#8203;feynman\.localnet   Branch​: perl   ! cv.h embed.h embed.pl objXSUB.h op.c perlapi.c pod/perlapi.pod   ! proto.h sv.c

If this _is_ a new feature of 5.8.0\, maybe it should be at least documented in the 5.8.2 perldelta? And possible somewhere else. Suggestions for locations where this should be documented? I'll write up a description and submit a patch then.

I suspect it is a bug in the code that determines if a sub can be considered a constant sub and was introduced during 5.7 development

No\, I think its a deliberate feature (but I could be wrong!) In particular from that patch​:

+ + if (CvCONST(cv)) { + SV* const_sv = op_const_sv(CvSTART(cv)\, cv); + assert(const_sv); + /* constant sub () { $x } closing over $x - see lib/constant.pm */   ^^^^^^^^^^^^^

-- 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.

p5pRT commented 20 years ago

From perl_dummy@bloodgate.com

-----BEGIN PGP SIGNED MESSAGE-----

Moin\,

Dave Mitchell \davem@&#8203;fdgroup\.com​:

This isn't a bug\, it's a feature :-)

sub () {$lexical} is a constant sub generator\, ie each call to 'sub' returns a new constant sub rather than a closure.

Oh. That got me by surprise. I thought that I followed p5p quite closely\, but someone introcuded a new bug^H^H^Hfeature while I was not looking. And a confusing one. I think these should not be different​:

  sub () { $lexical; }   sub () { return $lexical; }

Best wishes\,

Tels

- -- Signed on Mon Oct 20 18​:54​:19 2003 with key 0x93B84C15. Visit my photo gallery at http​://bloodgate.com/photos/ PGP key on http​://bloodgate.com/tels.asc or per email.

"Yeah\, baby\, yeah!"

-----BEGIN PGP SIGNATURE----- Version​: GnuPG v1.2.2-rc1-SuSE (GNU/Linux) Comment​: When cryptography is outlawed\, bayl bhgynjf jvyy unir cevinpl.

iQEVAwUBP5QTkncLPEOTuEwVAQE85gf+KtNnAsgerq4BpXMKTCvfk7VKnvlPnA2m neuMEtVGB8wgk1ZyC4jNzn42c2/34DtLbmtEdIjGVuumSlTDX6aYq/0FLMWcwvdj tvWdCsOPpcpYEk84ChxYgQhokzbeXNnWBzDSlEP8cq/Eiv4R6zxIt49713OnN/qx BfowOCZmUtcdRfQhOchiLtsZUebDRt2FXvORumse8ltK92feGTYpInho/8JPAdnr 0UkF45NFVHBYtCEGNEaj4ZFpdkY8b7/kAwPUkzr1kcq9LVq9vpC+LS6uCM6lf+TG xFt3R7wEYgcCRKml5/d8wymRuuJNgxEoOXqvOEBmarH78pz7mm2QOA== =XQ90 -----END PGP SIGNATURE-----

p5pRT commented 20 years ago

From @gbarr

On 20 Oct 2003\, at 17​:48\, Dave Mitchell wrote​:

On Mon\, Oct 20\, 2003 at 04​:59​:20PM +0100\, Graham Barr wrote​:

It is only supposed to generate a constant sub if there are no other references to the variable. ie there is no way the variable can change.

But it's easy to create a reference after the event​:

sub new\_constant\_sub \{
my $val = shift;
my $s = sub\(\) \{$val\};    \# only one ref\, so $s a const sub

But that is not when its decided that its a constant sub. Or at least originally it was not.

When constant subs were first introduced it was in the optimizer that the decision was taken if a sub was constant\, not when the sab was made. The decision was "does the sub being called have a proto of () and is its body a single scalar with a refcnt of 1"\, if yes then inline it.

I am guessing that logic has been pushed back to when the sub is defined\, which has resulted in this bug

Graham.

$global = \\$val;    \# whoops
$s;
\}

I always thought you would need to document a bug before it becomes a feature? ;-)

Seriously\, I haven't been able to find _any_ documentation on this feature. It definitely is not mentioned in the 5.8.0 perldelta (or it is described without the terms "constant" or "generator").

Constant subs were in 5.6.0 IIRC

but anonymous 'const sub generators' were only introduced in 5.8.0\, by

[ 7389] By​: jhi on 2000/10/21
14​:26​:45 Log​: Subject​: Re​: Creating const subs for constants. From​: John Tobey \jtobey@&#8203;john\-edwin\-tobey\.org Date​: Fri\, 20 Oct 2000 22​:03​:27 -0400 (EDT) Message-Id​: \m13mo0N\-000FObC@&#8203;feynman\.localnet Branch​: perl ! cv.h embed.h embed.pl objXSUB.h op.c perlapi.c pod/perlapi.pod ! proto.h sv.c

If this _is_ a new feature of 5.8.0\, maybe it should be at least documented in the 5.8.2 perldelta? And possible somewhere else. Suggestions for locations where this should be documented? I'll write up a description and submit a patch then.

I suspect it is a bug in the code that determines if a sub can be considered a constant sub and was introduced during 5.7 development

No\, I think its a deliberate feature (but I could be wrong!) In particular from that patch​:

+ + if (CvCONST(cv)) { + SV* const_sv = op_const_sv(CvSTART(cv)\, cv); + assert(const_sv); + /* constant sub () { $x } closing over $x - see lib/constant.pm */ ^^^^^^^^^^^^^

-- 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.

p5pRT commented 20 years ago

From @ysth

On Sun\, Oct 19\, 2003 at 11​:01​:42PM -0000\, "martin@​suttles.sca.sfbay.sun.com (via RT)" \perlbug\-followup@&#8203;perl\.org wrote​:

my $count = 0; my $x = [sub() { $count }\, sub() { return $count }\, sub($) { $count += $_[0] }]; $x->[2](3); printf "%d %d\n"\, $x->[0]()\, $x->[1]();

This prints 0 3 when it should print 3 3

The two anonymous subs $x->[0] and $x->[1] should have exactly the same effect because `return' is supposed to be redundant when returning the last expression in a sub.

This surprising behaviour is intentional. See perlsub/Constant Functions. The doc there could use some improvement to mention anonymous subs. (Note that constant.pm relies on this behaviour.)

Actually\, there does seem to be a bug here. If you reverse the order of the first two subs\, $count should have an extra refcnt that should prevent the constant sub\, but it doesn't work that way. This seems to be fixed in bleadperl.

p5pRT commented 20 years ago

From @iabyn

On Mon\, Oct 20\, 2003 at 06​:20​:13PM +0100\, Graham Barr wrote​:

On 20 Oct 2003\, at 17​:48\, Dave Mitchell wrote​:

On Mon\, Oct 20\, 2003 at 04​:59​:20PM +0100\, Graham Barr wrote​:

It is only supposed to generate a constant sub if there are no other references to the variable. ie there is no way the variable can change.

But it's easy to create a reference after the event​:

sub new_constant_sub { my $val = shift; my $s = sub() {$val}; # only one ref\, so $s a const sub

But that is not when its decided that its a constant sub. Or at least originally it was not.

When constant subs were first introduced it was in the optimizer that the decision was taken if a sub was constant\, not when the sab was made. The decision was "does the sub being called have a proto of () and is its body a single scalar with a refcnt of 1"\, if yes then inline it.

I am guessing that logic has been pushed back to when the sub is defined\, which has resulted in this bug

The 5.6.0 behaviour was that subs (named or anon) were not marked as CONST at compile time; instead at every compile-time appearance of a sub call\, the sub was checked for having a constant value or a single lexical with refcount\<2\, and if so the OP_ENTERSUB was replaced with an OP_CONST.

This meant that C\ cloned a full heavyweight anon sub for each defined constant.

In 5.8.0\, sub f(){1}-style subs were detected at compile time as being constant\, and if so\, replaced with CvCONSTs. sub(){$x}'s were detected as being CONST *candidates* at compile time if the refcnt of $x was \< 2. Then each time they were cloned\, the current value of $x was copied to make a new CvCONST sub. Due to the vagarites of lexical bugs prior to bleedperl\, the compile-time test for the lexical refcnt being \< 2 was not always very DWIM.

In bleedperl\, I changed it to a hybrid behaviour. At compile time\, the anon CV prototype is marked as a CONST candidate if it contains a single outer lexical. At clone time\, the cloned CV is converted into a CvCONST if the lexical has a refcnt \< 2.

Thus\, the refcnt\<2 test is done​:

5.6.0​: sometime after cloning\, when the sub call is being compiled 5.6.0​: when the anon sub is compiled bleed​: when the anon sub is cloned

Both the 5.8.0 and bleedperl behaviours have problems\, and are very sensitive to their environments\, and will generally do things that people find unexpected.

Thus\, I like Elizabeth's suggestion of using a compile-time attribute to explicitly turn on this special behaviour\, and thus to not suprise the ordinary user.

Dave.

-- O Unicef Clearasil! Gibberish and Drivel!   - "Bored of the Rings"

p5pRT commented 20 years ago

From @nwc10

On Mon\, Oct 20\, 2003 at 11​:53​:03PM +0100\, Dave Mitchell wrote​:

Thus\, I like Elizabeth's suggestion of using a compile-time attribute to explicitly turn on this special behaviour\, and thus to not suprise the ordinary user.

I like it\, but I'm worried that I may be hasty\, so I'd like to to simmer for a bit more before committing anything half baked to maint. (Woohoo. Mixed metaphors. Flavour clash)

It would be nice if this (or something related) also provided a solution to how to export constants that can be autoloaded. Currently all the core extensions (such as Fcntl\, POSIX\, Socket ...) have @​EXPORT or @​EXPORT_OK full of names of "subs" that are actually defined as needed by AUTOLOAD (these days usually by a call into code generated by ExtUtils​::Constant\, but that's not important).

As these "subroutines" are actually constant value returning\, it would be nice if

a​: there was a way to declare them them from henceforth to be constants   without getting the prototype redefinition warning. (And its implication   that you're making a real change to the parsing behaviour)

  (Maybe I'm confused. Maybe we just need Exporter to declare them with   a prototype) (Without making it slower)

b​: there was a way to make the tokenizer/optimizer whatever call the sub   to find the value whenever it is referred to. (given that it's actually   a constant sub)

Note that you can't simply call the AUTOLOAD routine on all the subs as you export them\, as there are bazillions\, and most are not used by most programs.

Nicholas Clark

p5pRT commented 20 years ago

From @iabyn

On Tue\, Oct 21\, 2003 at 12​:05​:44AM +0100\, Nicholas Clark wrote​:

On Mon\, Oct 20\, 2003 at 11​:53​:03PM +0100\, Dave Mitchell wrote​:

Thus\, I like Elizabeth's suggestion of using a compile-time attribute to explicitly turn on this special behaviour\, and thus to not suprise the ordinary user.

I like it\, but I'm worried that I may be hasty\, so I'd like to to simmer for a bit more before committing anything half baked to maint. (Woohoo. Mixed metaphors. Flavour clash)

It would be nice if this (or something related) also provided a solution to how to export constants that can be autoloaded. Currently all the core extensions (such as Fcntl\, POSIX\, Socket ...) have @​EXPORT or @​EXPORT_OK full of names of "subs" that are actually defined as needed by AUTOLOAD (these days usually by a call into code generated by ExtUtils​::Constant\, but that's not important).

As these "subroutines" are actually constant value returning\, it would be nice if

a​: there was a way to declare them them from henceforth to be constants without getting the prototype redefinition warning. (And its implication that you're making a real change to the parsing behaviour)

(Maybe I'm confused. Maybe we just need Exporter to declare them with a prototype) (Without making it slower)

b​: there was a way to make the tokenizer/optimizer whatever call the sub to find the value whenever it is referred to. (given that it's actually a constant sub)

Note that you can't simply call the AUTOLOAD routine on all the subs as you export them\, as there are bazillions\, and most are not used by most programs.

I'm not sure I understand all of the above\, but...

An idea occurs to me.

Ilya introduced a patch that allowed stash values to be an IV or a PV rather than a full-blown GV+CV when a sub had only been declared rather than defined (IV => no protoptye\, PV => protoptye with the PVX containing the protoptye string). Only later when the sub was actually defined was the IV/PV replaced with a full GV containing a CV. This allowed Exporter to whack lots of sub declarations into the caller's namespace without a big memory overhead.

I wonder whether this idea could be extended - so for constant subs where the package has no other variable of the same name\, then rather than having a GV pointing to a const CV\, the stash just contains a "something" (perhaps a PV with the right flags set) that actually holds the const value. This PV would be shared by each packahge that imports it.

We would have to provide mechanisms a) for the module to create all the values in its own namespace when compiled; b) for Exporter to cheaply copy these to the callers namespace.

Here endeth the 1am vague handwaving. Time for bed (said Zebedee).

Dave.

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

p5pRT commented 20 years ago

From @iabyn

On Tue\, Oct 21\, 2003 at 12​:05​:44AM +0100\, Nicholas Clark wrote​:

On Mon\, Oct 20\, 2003 at 11​:53​:03PM +0100\, Dave Mitchell wrote​:

Thus\, I like Elizabeth's suggestion of using a compile-time attribute to explicitly turn on this special behaviour\, and thus to not suprise the ordinary user.

I like it\, but I'm worried that I may be hasty\, so I'd like to to simmer for a bit more before committing anything half baked to maint. (Woohoo. Mixed metaphors. Flavour clash)

(Now 2am. Have had a bath. Should have quitted while ahead at 1am; instead I'm going to throw an even more hare-brained idea out that I will regret in the morning).

I provisonally propose the new syntax​:

  sub foo() : constant { ...} and   sub() : constant { ...}

which has the effect of​:

for a named sub​: as soon as the sub is compiled\, it is executed once in scalar context\, and the return value is used at the basis for a new CONST CV which replaces the original CV.

ie roughly speaking

  sub foo() : constant { $x + $y }

is about equivalent to

  sub foo() { $x + $y }   BEGIN {   my $val = foo();   no warnings 'redefine';   eval 'sub foo() { "' . $val . "}'   }

For an anon sub\, the execution is done each time the sub is cloned\, ie

  $a = sub() : constant { $x + $y }

is about equivalent to

  $a = sub() { $x + $y };   my $val = $a->();   $a = eval 'sub () { "' . $val . "}'

Of course we can optimise the common cases of {1} or {$x} like we do at the moment\, so we don't actually have to execute the sub then throw it away to determine its value.

Having implemeted this\, would would immediately throw away the special sub(){$outer_lexical} behaviour\, on the grounds that it is horrible\, is undocumented\, and has only been around since 5.8.0.

More controversially\, we might then want to deprecate the whole "sub foo(){1} is a constant sub" syntax\, on the grounds that it's a none-intuitive hack; posssibly even with the warning 'use :constant instead'.

But I've never been any good at language design...

(Hey\, we could roll it out in 5.8.2\, and if the community likes it\, we could backport it into bleedperl....;-)

-- 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.

p5pRT commented 20 years ago

From @rgs

Dave Mitchell wrote​:

I provisonally propose the new syntax​:

sub foo\(\) : constant \{ \.\.\.\}

and sub() : constant { ...}

which has the effect of​:

for a named sub​: as soon as the sub is compiled\, it is executed once in scalar context\, and the return value is used at the basis for a new CONST CV which replaces the original CV.

At least Eiffel uses the keyword "once" for such subroutines (that are executed once.) It may be more clear.

Offhand I don't remember seeing something like this in Perl 6.

p5pRT commented 20 years ago

From @lizmat

At 07​:51 +0200 10/21/03\, Rafael Garcia-Suarez wrote​:

Dave Mitchell wrote​:

I provisonally propose the new syntax​:

 sub foo\(\) : constant \{ \.\.\.\}

and sub() : constant { ...}

which has the effect of​:

for a named sub​: as soon as the sub is compiled\, it is executed once in scalar context\, and the return value is used at the basis for a new CONST CV which replaces the original CV. At least Eiffel uses the keyword "once" for such subroutines (that are executed once.) It may be more clear.

I guess it's a matter of what it is used for and how it does it. German used to have a word for modem that described what it does​: "Datenfernuebertragungsanlage" (device to transfer data over large distances). I'm sure glad Germans now also understand "modem" (which\, at least initially\, described _how_ it's done​: modulation / demodulation). Saves a lot on the keyboard and screen space (try translating English courseware to German within the same screen space ;-).

I like the "once" because it's shorter. On the other hand\, "once" is not a good description. In that sense\, "cached" or "memoized" would be a better description.

Finally\, I think it still is a (bad) hack to have constants in a language as a sort of second class subroutines with all the oddities involved (most notably\, not being able to use constants in a double quoted string). So maybe we should keep it like it is (but document it better) until we figure out what is best. There are plenty of other things in Perl5 that catch people unsuspectedly. I think we can live with it.

Offhand I don't remember seeing something like this in Perl 6.

Aren't Perl6's (constant) macro's really what we're talking about here?

Liz

p5pRT commented 20 years ago

From @iabyn

On Tue\, Oct 21\, 2003 at 12​:57​:45PM +0200\, Elizabeth Mattijsen wrote​:

Finally\, I think it still is a (bad) hack to have constants in a language as a sort of second class subroutines with all the oddities involved (most notably\, not being able to use constants in a double quoted string). So maybe we should keep it like it is (but document it better) until we figure out what is best. There are plenty of other things in Perl5 that catch people unsuspectedly. I think we can live with it.

My attitude is​:

* implementing bareword constants using subs is a hack\, but is the best we can do for Perl5.

* given that for Perl 5 we need a way of creating const subs\, and given that the current technique in constant.pm of using anon subs has poorly-defined and fragile semantics that is likely to trip up casual users of closures (hence this bug report)\, I think we need a different mechanism for creating them.

* I can live with the idea that this new method be marked experimental\, that we don't advertise it\, that is it never used outside of constant.pm\, and that the attribute is named

  __llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch__

Dave.

-- "I do not resent critisism\, even when\, for the sake of emphasis\, it parts for the time with reality". Winston Churchill\, House of Commons\, 22nd Jan 1941.

p5pRT commented 20 years ago

From @lizmat

At 13​:18 +0100 10/21/03\, Dave Mitchell wrote​:

* I can live with the idea that this new method be marked experimental\, that we don't advertise it\, that is it never used outside of constant.pm\, and that the attribute is named

\_\_llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch\_\_

Continuing on this thought\, why not change the XS code so that the special constant routine definition is only done when called from "constant.pm" ? It wouldn't require any outwardly visibility otherwise. And if someone really puts a "package constant" in their code to get this behaviour\, then they're _really_ getting what they're asking for.

Liz

p5pRT commented 20 years ago

From @hvds

Dave Mitchell \davem@&#8203;fdgroup\.com wrote​: :I provisonally propose the new syntax​: [...] :ie roughly speaking : : sub foo() : constant { $x + $y } : :is about equivalent to : : sub foo() { $x + $y } : BEGIN { : my $val = foo(); : no warnings 'redefine'; : eval 'sub foo() { "' . $val . "}' : }

The biggest problem I see with that is this​:   future% perl -wle 'my $pi = 3; sub pi () : constant { $pi } print pi()'   Use of uninitialized value in concatenation (.) or string at -e line 1.  
  future%

I'm in at least two minds about how big a problem that actually is.

Hugo

p5pRT commented 20 years ago

From @iabyn

On Tue\, Oct 21\, 2003 at 02​:11​:32PM +0100\, hv@​crypt.org wrote​:

Dave Mitchell \davem@&#8203;fdgroup\.com wrote​: :I provisonally propose the new syntax​: [...] :ie roughly speaking : : sub foo() : constant { $x + $y } : :is about equivalent to : : sub foo() { $x + $y } : BEGIN { : my $val = foo(); : no warnings 'redefine'; : eval 'sub foo() { "' . $val . "}' : }

The biggest problem I see with that is this​: future% perl -wle 'my $pi = 3; sub pi () : constant { $pi } print pi()' Use of uninitialized value in concatenation (.) or string at -e line 1.

future%

I'm in at least two minds about how big a problem that actually is.

Well\, it's better than the current behaviour because you don't even get a constant at the moment​:

./perl -wle 'my $pi = 3; sub pi () { $pi } print pi; $pi++; print pi;' 3 4

-- "Emacs isn't a bad OS once you get used to it. It just lacks a decent editor."

p5pRT commented 20 years ago

From Robin.Barker@npl.co.uk

I found the follow bug today\, I think it may be related to this one.

% perl5.8.1 -lwe 'sub a {} print main->a' main % perl5.8.0 -lwe 'sub a {} print main->a'

% perl5.8.1 -lwe 'sub a {return} print main->a'

% perl5.8.0 -lwe 'sub a {return} print main->a'

So when the method is empty rather than {return} in perl5.8.1 the object is returned.

Robin

-----Original Message----- From​: Dave Mitchell [mailto​:davem@​fdgroup.com] Sent​: 21 October 2003 14​:33 To​: hv@​crypt.org Cc​: Subject​: Re​: [perl #24250] "return" required in some anonymous closures

On Tue\, Oct 21\, 2003 at 02​:11​:32PM +0100\, hv@​crypt.org wrote​:

Dave Mitchell \davem@&#8203;fdgroup\.com wrote​: :I provisonally propose the new syntax​: [...] :ie roughly speaking : : sub foo() : constant { $x + $y } : :is about equivalent to : : sub foo() { $x + $y } : BEGIN { : my $val = foo(); : no warnings 'redefine'; : eval 'sub foo() { "' . $val . "}' : }

The biggest problem I see with that is this​: future% perl -wle 'my $pi = 3; sub pi () : constant { $pi } print pi()' Use of uninitialized value in concatenation (.) or string at -e line 1.

future%

I'm in at least two minds about how big a problem that actually is.

Well\, it's better than the current behaviour because you don't even get a constant at the moment​:

./perl -wle 'my $pi = 3; sub pi () { $pi } print pi; $pi++; print pi;' 3 4

-- "Emacs isn't a bad OS once you get used to it. It just lacks a decent editor."


This e-mail and any attachments may contain confidential and/or privileged material; it is for the intended addressee(s) only. If you are not a named addressee\, you must not use\, retain or disclose such information.

NPL Management Ltd cannot guarantee that the e-mail or any attachments are free from viruses.

NPL Management Ltd. Registered in England and Wales. No​: 2937881 Registered Office​: Teddington\, Middlesex\, United Kingdom TW11 0LW.


p5pRT commented 20 years ago

From @iabyn

On Tue\, Oct 21\, 2003 at 02​:51​:32PM +0100\, Robin Barker wrote​:

I found the follow bug today\, I think it may be related to this one.

% perl5.8.1 -lwe 'sub a {} print main->a' main % perl5.8.0 -lwe 'sub a {} print main->a'

% perl5.8.1 -lwe 'sub a {return} print main->a'

% perl5.8.0 -lwe 'sub a {return} print main->a'

So when the method is empty rather than {return} in perl5.8.1 the object is returned.

more accturately\, @​_ is returned​:

$perl5.8.1 -lwe 'sub a {}; print a(3\,4\,5)' 345

-- "Emacs isn't a bad OS once you get used to it. It just lacks a decent editor."

p5pRT commented 20 years ago

From @iabyn

On Tue\, Oct 21\, 2003 at 02​:32​:32PM +0100\, Dave Mitchell wrote​:

On Tue\, Oct 21\, 2003 at 02​:11​:32PM +0100\, hv@​crypt.org wrote​:

Dave Mitchell \davem@&#8203;fdgroup\.com wrote​: :I provisonally propose the new syntax​: [...] :ie roughly speaking : : sub foo() : constant { $x + $y } : :is about equivalent to : : sub foo() { $x + $y } : BEGIN { : my $val = foo(); : no warnings 'redefine'; : eval 'sub foo() { "' . $val . "}' : }

The biggest problem I see with that is this​: future% perl -wle 'my $pi = 3; sub pi () : constant { $pi } print pi()' Use of uninitialized value in concatenation (.) or string at -e line 1.

future%

I'm in at least two minds about how big a problem that actually is.

After more thought\, I now think that :constant is unnecessary baggage; my preferred solution for today is to add XS to constant.pm so that it just efficently does lots of newCONTSUB()s without requiring any language hooks. The sub(){$lex} hack is quietly retired\, and the standard sub name {1} construct is kept for those who are emotionally attached to it.

If any cleverer ways are devised of handling large numbers of imported constants\, a la POSIX\, then Export.pm and/or constant.pm can be hacked to accomodate them.

No doubt tomorrow\, like the wind\, I shall blow in a new direction...

-- This is a great day for France!   -- Nixon at Charles De Gaulle's funeral

p5pRT commented 20 years ago

From @nwc10

On Tue\, Oct 21\, 2003 at 08​:09​:57PM +0100\, Dave Mitchell wrote​:

If any cleverer ways are devised of handling large numbers of imported constants\, a la POSIX\, then Export.pm and/or constant.pm can be hacked to accomodate them.

No doubt tomorrow\, like the wind\, I shall blow in a new direction...

This is why I think it would not be wise to change anything for 5.8.2 :-)

Assuming 5.8.2 is soon\, then code freeze for 5.8.3 will be 23​:59 on 31st Dec 2003. We all have a few months.

Nicholas Clark

p5pRT commented 20 years ago

From @ysth

On Tue\, Oct 21\, 2003 at 08​:09​:57PM +0100\, Dave Mitchell \davem@&#8203;fdgroup\.com wrote​:

On Tue\, Oct 21\, 2003 at 02​:32​:32PM +0100\, Dave Mitchell wrote​:

On Tue\, Oct 21\, 2003 at 02​:11​:32PM +0100\, hv@​crypt.org wrote​:

Dave Mitchell \davem@&#8203;fdgroup\.com wrote​: :I provisonally propose the new syntax​: [...] :ie roughly speaking : : sub foo() : constant { $x + $y } : :is about equivalent to : : sub foo() { $x + $y } : BEGIN { : my $val = foo(); : no warnings 'redefine'; : eval 'sub foo() { "' . $val . "}' : }

The biggest problem I see with that is this​: future% perl -wle 'my $pi = 3; sub pi () : constant { $pi } print pi()' Use of uninitialized value in concatenation (.) or string at -e line 1.

future%

I'm in at least two minds about how big a problem that actually is.

After more thought\, I now think that :constant is unnecessary baggage; my preferred solution for today is to add XS to constant.pm so that it just efficently does lots of newCONTSUB()s without requiring any language hooks. The sub(){$lex} hack is quietly retired\, and the standard sub name {1} construct is kept for those who are emotionally attached to it.

If any cleverer ways are devised of handling large numbers of imported constants\, a la POSIX\, then Export.pm and/or constant.pm can be hacked to accomodate them.

That doesn't sound like something to do for 5.8.2 if released in a few weeks. How doable would it be to give a warning for "const" padsv anon subs\, and just have constant.pm turn off the warning?

No doubt tomorrow\, like the wind\, I shall blow in a new direction...

p5pRT commented 20 years ago

From @iabyn

On Tue\, Oct 21\, 2003 at 12​:54​:53PM -0700\, Yitzchak Scott-Thoennes wrote​:

That doesn't sound like something to do for 5.8.2 if released in a few weeks. How doable would it be to give a warning for "const" padsv anon subs\, and just have constant.pm turn off the warning?

Technically very easy. I guess we now renew that thorny old argument about adding new deprecation warnings to maintenance releases\, and lesser of two evils etc etc.

Lets see​:

  Anonymous subroutine interpreted as constant sub generator at line 1 or   Lexical variable $foo treated as a constant in anonymous sub at line 1 or   This closure - I don't think it means what you think it means at line 1

Presumably with perldiag filling in the gory details.

-- "Emacs isn't a bad OS once you get used to it. It just lacks a decent editor."

p5pRT commented 20 years ago

From @lizmat

At 12​:54 -0700 10/21/03\, Yitzchak Scott-Thoennes wrote​:

If any cleverer ways are devised of handling large numbers of imported constants\, a la POSIX\, then Export.pm and/or constant.pm can be hacked to accomodate them. That doesn't sound like something to do for 5.8.2 if released in a few weeks. How doable would it be to give a warning for "const" padsv anon subs\, and just have constant.pm turn off the warning?

The way I understand it now\, is that the check for making this special case is somehow wrong. How difficult would it be to add a check there that it would do the optimization if the current package is "constant.pm" ? And just not do the optimization otherwise?

Just as a stopgap for now...

Liz

p5pRT commented 20 years ago

From @demerphq

The way I understand it now\, is that the check for making this special case is somehow wrong. How difficult would it be to add a check there that it would do the optimization if the current package is "constant.pm" ? And just not do the optimization otherwise?

Lots of modules build their own constants using this technique to avoid the load time overhead associated with use constant. Carp​::Assert comes to mind.

I know its not the best call\, but it is true.

Yves

p5pRT commented 20 years ago

From @iabyn

On Tue\, Oct 21\, 2003 at 09​:17​:59PM +0100\, Orton\, Yves wrote​:

The way I understand it now\, is that the check for making this special case is somehow wrong. How difficult would it be to add a check there that it would do the optimization if the current package is "constant.pm" ? And just not do the optimization otherwise?

Lots of modules build their own constants using this technique to avoid the load time overhead associated with use constant. Carp​::Assert comes to mind.

We're not here talking about named subs with constant values such as

  sub REAL_DEBUG () { 1 }

but anonymous subs containing a single outer lexical that under some circumstances is interpreted by Perl as a const sub factory (each time you call it you get a new const sub).

Carp​::Assert only appears to use the former\, and there's no talk of that feature going way.  
-- Never do today what you can put off till tomorrow.

p5pRT commented 20 years ago

From @iabyn

On Tue\, Oct 21\, 2003 at 10​:14​:48PM +0200\, Elizabeth Mattijsen wrote​:

At 12​:54 -0700 10/21/03\, Yitzchak Scott-Thoennes wrote​:

If any cleverer ways are devised of handling large numbers of imported constants\, a la POSIX\, then Export.pm and/or constant.pm can be hacked to accomodate them. That doesn't sound like something to do for 5.8.2 if released in a few weeks. How doable would it be to give a warning for "const" padsv anon subs\, and just have constant.pm turn off the warning?

The way I understand it now\, is that the check for making this special case is somehow wrong. How difficult would it be to add a check there that it would do the optimization if the current package is "constant.pm" ? And just not do the optimization otherwise?

Just as a stopgap for now...

In the medium-term\, I want to remove the sub(){$x} feature from Perl\, and also make constant.pm do it another way. Both are relatively easy to do (although in the longer term there may be even cleverer ways of doing it in constant.pm that would be harder to do but more efficient). However\, in the short term (ie for 5.8.2)\, neither of these changes should happen (I'm not even sure if they should happen in any 5.8.x release).

So the only real question for 5.8.2 is whether we want to add a deprecation warning for the feature we added (undocumented) in 5.8.0 and which we intend to remove in 5.10.0 (conscensus permitting).

Dave.

-- "There's something wrong with our bloody ships today\, Chatfield." Admiral Beatty at the Battle of Jutland\, 31st May 1916.

p5pRT commented 20 years ago

From @ysth

On Tue\, Oct 21\, 2003 at 09​:34​:24PM +0100\, Dave Mitchell \davem@&#8203;fdgroup\.com wrote​:

On Tue\, Oct 21\, 2003 at 10​:14​:48PM +0200\, Elizabeth Mattijsen wrote​:

At 12​:54 -0700 10/21/03\, Yitzchak Scott-Thoennes wrote​:

If any cleverer ways are devised of handling large numbers of imported constants\, a la POSIX\, then Export.pm and/or constant.pm can be hacked to accomodate them. That doesn't sound like something to do for 5.8.2 if released in a few weeks. How doable would it be to give a warning for "const" padsv anon subs\, and just have constant.pm turn off the warning?

The way I understand it now\, is that the check for making this special case is somehow wrong. How difficult would it be to add a check there that it would do the optimization if the current package is "constant.pm" ? And just not do the optimization otherwise?

Just as a stopgap for now...

In the medium-term\, I want to remove the sub(){$x} feature from Perl\, and also make constant.pm do it another way. Both are relatively easy to do (although in the longer term there may be even cleverer ways of doing it in constant.pm that would be harder to do but more efficient). However\, in the short term (ie for 5.8.2)\, neither of these changes should happen (I'm not even sure if they should happen in any 5.8.x release).

Given that we have a report of the feature breaking code as of 5.8.0\, it would be advisable to fix it in the end-of-yearish 5.8.x release.

So the only real question for 5.8.2 is whether we want to add a deprecation warning for the feature we added (undocumented) in 5.8.0 and which we intend to remove in 5.10.0 (conscensus permitting).

The point of a warning seems more to me to be for when the coder didn't want a constant that for when he/she did.

p5pRT commented 20 years ago

From @iabyn

On Tue\, Oct 21\, 2003 at 01​:46​:27PM -0700\, Yitzchak Scott-Thoennes wrote​:

On Tue\, Oct 21\, 2003 at 09​:34​:24PM +0100\, Dave Mitchell \davem@&#8203;fdgroup\.com wrote​:

In the medium-term\, I want to remove the sub(){$x} feature from Perl\, and also make constant.pm do it another way. Both are relatively easy to do (although in the longer term there may be even cleverer ways of doing it in constant.pm that would be harder to do but more efficient). However\, in the short term (ie for 5.8.2)\, neither of these changes should happen (I'm not even sure if they should happen in any 5.8.x release).

Given that we have a report of the feature breaking code as of 5.8.0\, it would be advisable to fix it in the end-of-yearish 5.8.x release.

Perhaps\, but its been broken for 1.5 years befor anyone noticed. During that time people may have added code that indadvertently uses the new behaviour and so would break if reverted.

So the only real question for 5.8.2 is whether we want to add a deprecation warning for the feature we added (undocumented) in 5.8.0 and which we intend to remove in 5.10.0 (conscensus permitting).

The point of a warning seems more to me to be for when the coder didn't want a constant that for when he/she did.

i *think* that's what I was saying. Every time Perl does the strange 5.8.0-ish convertion to a constant\, you would get the warning. Normal closures would be silent.

-- In the 70's we wore flares because we didn't know any better. What possible excuse does the current generation have?