Perl / perl5

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

Closure/lexical inconsistency #7029

Closed p5pRT closed 20 years ago

p5pRT commented 20 years ago

Migrated from rt.perl.org#24881 (status was 'resolved')

Searchable as RT24881$

p5pRT commented 20 years ago

From tassilo.parseval@post.rwth-aachen.de

Created by tassilo.parseval@post.rwth-aachen.de

Consider this code that expectedly does the wrong thing​:

  {   my $d = 'xxx';   sub foo {   my ($b\, $c);   $b = '$d';   $c = eval("\"$b\"");   print "$c\n";   }   }   foo();

No problem here​: Perl doesn't see that foo() contains a hidden reference to $d and so the garbage collector has already cleaned up $d when foo() is called.

But what about this here​:

  {   my $d;   sub foo {   my ($b\, $c);   $b = '$d';   $c = eval("\"$b\"");   print "$c\n";   }   sub bar {   $d = 'xxx';   foo();   }   }   bar();

In my understanding\, the mentioning of $d in bar should keep $d alive by the time foo() is called.

I am not sure\, whether this is a known issue.

Perl Info ``` Flags: category=core severity=low Site configuration information for perl v5.8.2: Configured by root at Fri Nov 14 07:29:04 UTC 2003. Summary of my perl5 (revision 5.0 version 8 subversion 2) configuration: Platform: osname=linux, osvers=2.4.21, archname=i686-linux uname='linux ethan 2.4.21 #3 tue nov 11 09:22:00 utc 2003 i686 unknown ' config_args='' 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 ='-fno-strict-aliasing -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64', optimize='-O3 -march=athlon -fomit-frame-pointer -foptimize-sibling-calls -finline-functions -fstrength-reduce -frerun-loop-opt -fexpensive-optimizations -fprefetch-loop-arrays -fmove-all-movables', cppflags='-fno-strict-aliasing' ccversion='', gccversion='3.2', gccosandvers='' intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234 d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12 ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8 alignbytes=4, prototype=define Linker and Libraries: ld='cc', ldflags =' -L/usr/local/lib' libpth=/usr/local/lib /lib /usr/lib libs=-lnsl -ldb -ldl -lm -lcrypt -lutil -lc perllibs=-lnsl -ldl -lm -lcrypt -lutil -lc libc=/lib/libc-2.2.5.so, so=so, useshrplib=false, libperl=libperl.a gnulibc_version='2.2.5' Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-rdynamic' cccdlflags='-fpic', lddlflags='-shared -L/usr/local/lib' Locally applied patches: @INC for perl v5.8.2: /usr/opt/perl5.8.2/lib/5.8.2/i686-linux /usr/opt/perl5.8.2/lib/5.8.2 /usr/opt/perl5.8.2/lib/site_perl/5.8.2/i686-linux /usr/opt/perl5.8.2/lib/site_perl/5.8.2 /usr/opt/perl5.8.2/lib/site_perl . Environment for perl v5.8.2: HOME=/home/ethan LANG=C LANGUAGE (unset) LC_CTYPE=de_DE@euro LD_LIBRARY_PATH=:/usr/local/j2sdk1.4.0/jre/lib/i386:/usr/local/pwlib/lib:/usr/local/lib LOGDIR (unset) PATH=/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/usr/games:/usr/local/j2re1.4.1/bin:/usr/local/mpich-1.2.5/ch_p4/bin PERLDOC_PAGER=/bin/less -isR PERL_BADLANG (unset) SHELL=/bin/bash ```
p5pRT commented 20 years ago

From perl@nevcal.com

On approximately 1/12/2004 2​:20 AM\, came the following characters from the keyboard of Tassilo v.Parseval (via RT)​:

But what about this here​:

\{
    my $d;
    sub foo \{
        my \($b\, $c\);
        $b = '$d';
        $c = eval\("\\"$b\\""\);
        print "$c\\n";
    \}
    sub bar \{
        $d = 'xxx';
        foo\(\);
    \}
\}
bar\(\);

In my understanding\, the mentioning of $d in bar should keep $d alive by the time foo() is called.

I am not sure\, whether this is a known issue.

This was beaten to death in the "ignorant wumpus" thread due to my ignorance.

Now\, to hopefully save Dave a few of the tuits he used in that threads\, what you have there in your example is two separate subs\, 'foo' does not reference $d visibly (to the compiler at compile time) and 'bar' does\, and therefore becomes a closure.

The fact that the subs are enclosed in the same {} with the my $d does not make the pair of them a single closure. The fact that 'bar' contains a visible outer reference to $d is what makes it a closure\, but that does not affect and is not affected by 'foo' or the block containing $d.

Since 'foo' is not a closure\, it does not retain a reference to the original $d\, and when later invoked a new $d of the appropriate scope is   instantiated (and undef). Since 'bar' is a closure\, it retains a reference to the original value $d\, and modifies that original value. However\, 'bar's reference to $d is lexical in nature\, and is not shared by 'foo'.

So\, this is working as advertised. Or as it will be advertised\, once Dave's tuit supply allows him to finish his documentation improvements for closures.

-- Glenn -- http​://nevcal.com/

The best part about procrastination is that you are never bored\, because you have all kinds of things that you should be doing.

p5pRT commented 20 years ago

The RT System itself - Status changed from 'new' to 'open'

p5pRT commented 20 years ago

From tassilo.parseval@post.rwth-aachen.de

On Tue\, Jan 13\, 2004 at 05​:04​:39AM +0000 Glenn Linderman via RT wrote​:

On approximately 1/12/2004 2​:20 AM\, came the following characters from the keyboard of Tassilo v.Parseval (via RT)​:

But what about this here​:

\{
    my $d;
    sub foo \{
        my \($b\, $c\);
        $b = '$d';
        $c = eval\("\\"$b\\""\);
        print "$c\\n";
    \}
    sub bar \{
        $d = 'xxx';
        foo\(\);
    \}
\}
bar\(\);

In my understanding\, the mentioning of $d in bar should keep $d alive by the time foo() is called.

I am not sure\, whether this is a known issue.

This was beaten to death in the "ignorant wumpus" thread due to my ignorance.

Now\, to hopefully save Dave a few of the tuits he used in that threads\, what you have there in your example is two separate subs\, 'foo' does not reference $d visibly (to the compiler at compile time) and 'bar' does\, and therefore becomes a closure.

[ further explanation ]

Thanks for the details. I must have missed the thread you mentioned. So what happens does in fact contradict the concept of closures I had so far. Good that this is going to be documented.

Tassilo -- $_=q#"\,}])!JAPH!qq(tsuJ[{@​"tnirp}3..0}_$;//​::niam/s~=)]3[))_$-3(rellac(=_$({ pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus})!JAPH!qq(rehtona{tsuJbus#; $_=reverse\,s+(?\<=sub).+q#q!'"qq.\t$&."'!#+sexisexiixesixeseg;y~\n~~dddd;eval

p5pRT commented 20 years ago

@rgs - Status changed from 'open' to 'resolved'