Perl / perl5

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

Recursive lexically-scoped subroutines #199

Closed p5pRT closed 21 years ago

p5pRT commented 24 years ago

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

Searchable as RT1005$

p5pRT commented 24 years ago

From garethr@cre.canon.co.uk

If I run the program

  use strict;   sub factorial {   my $fact = sub {   my ($n) = @​_;   $n > 0 ? $n * $fact->($n-1) : 1;   };   $fact->(@​_);   }

I get the error

  Global symbol "$fact" requires explicit package name at fact.pl line 9.

The `perlsub' manpage states that

  A "my" declares the listed variables to be confined   (lexically) to the enclosing block\, conditional   (if/unless/elsif/else)\, loop   (for/foreach/while/until/continue)\, subroutine\, eval\, or   do/require/use'd file.

so I think that either Perl's behavour should be changed to match the documentation\, or the documentation should be made clearer.

(I know that I can rewrite `factorial' as

  sub factorial {   my $fact; $fact = sub {   my ($n) = @​_;   $n > 0 ? $n * $fact->($n-1) : 1;   };   $fact->(@​_);   }

in order to get it to work as intended. That's not what this report is about.)

Perl Info ``` Site configuration information for perl 5.00502: Configured by abw at Thu Nov 19 10:50:08 GMT 1998. Summary of my perl5 (5.0 patchlevel 5 subversion 2) configuration: Platform: osname=solaris, osvers=2.6, archname=sun4-solaris uname='sunos bandanna 5.6 generic_105181-03 sun4u sparc sunw,ultra-1 ' hint=previous, useposix=true, d_sigaction=define usethreads=undef useperlio=undef d_sfio=undef Compiler: cc='gcc', optimize='-O', gccversion=2.8.0 cppflags='-I/opt/gnu/include -I/user/perl/build/include' ccflags ='-I/opt/gnu/include -I/user/perl/build/include' stdchar='unsigned char', d_stdstdio=define, usevfork=false intsize=4, longsize=4, ptrsize=4, doublesize=8 d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16 alignbytes=8, usemymalloc=n, prototype=define Linker and Libraries: ld='gcc', ldflags ='-L/opt/gnu/lib -L/user/perl/build/lib' libpth=/opt/gnu/lib /lib /usr/lib /usr/ccs/lib /user/perl/build/lib libs=-lsocket -lnsl -lgdbm -ldl -lm -lc -lcrypt -ldb libc=/lib/libc.so, so=so, useshrplib=false, libperl=libperl.a Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags=' ' cccdlflags='-fPIC', lddlflags='-G -L/opt/gnu/lib -L/user/perl/build/lib' Locally applied patches: @INC for perl 5.00502: /apps/perl5/lib/5.00502/sun4-solaris /apps/perl5/lib/5.00502 /apps/perl5/lib/site_perl/5.005/sun4-solaris /apps/perl5/lib/site_perl/5.005 . Environment for perl 5.00502: HOME=/user/garethr LANG=C LD_LIBRARY_PATH=/usr/dt/lib:/usr/openwin/lib:/apps/X11R5/lib:/usr/lib LOGDIR (unset) PATH=/usr/dt/bin:/usr/openwin/bin:/bin:/usr/bin:/usr/ucb:/bin:/usr/bin:/cre/bin:/apps/gcc-2.8.0/bin:/apps/frame5/bin:/apps/emacs/bin:/apps/tex/bin:/apps/perl5/bin:/user/web/bin/scripts:/user/web/bin/SunOS-5.6:/apps/gnu/bin:/apps/mysql/bin:/usr/ccs/bin:/apps/X11R5/bin:/usr/openwin/bin PERL_BADLANG (unset) SHELL=/cre/bin/bash ```
p5pRT commented 21 years ago

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

p5pRT commented 21 years ago

From @iabyn

Date​: Fri\, 16 Jul 1999 15​:24​:38 +0100 If I run the program

use strict;
sub factorial \{
  my $fact = sub \{
    my \($n\) = @​\_;
    $n > 0 ? $n \* $fact\->\($n\-1\) : 1;
  \};
  $fact\->\(@​\_\);
\}

I get the error

Global symbol "$fact" requires explicit package name at fact\.pl

line 9.

The `perlsub' manpage states that

A "my" declares the listed variables to be confined
\(lexically\) to the enclosing block\, conditional
\(if/unless/elsif/else\)\, loop
\(for/foreach/while/until/continue\)\, subroutine\, eval\, or
do/require/use'd file\.

so I think that either Perl's behavour should be changed to match the documentation\, or the documentation should be made clearer.

What you are seeing here is a more glorified version of

  my $x = $x;

From perlsub.pod​:

  The declared variable is not introduced (is not visible) until after   the current statement. Thus\,

  my $x = $x;

  can be used to initialize a new $x with the value of the old $x\, and   the expression

  my $x = 123 and $x == 123

  is false unless the old $x happened to have the value C\<123>.

So the lexical $fact doesnt come into scope until the end of the assigment\, so the '$fact' seen within the anon sub is the global $​::fact\, which doesn't exist.

Dave M.

p5pRT commented 21 years ago

From @iabyn

notabug.

p5pRT commented 21 years ago

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