Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug or wrong doc for 'foreach $lexical' #7224

Open
p5pRT opened this issue Apr 9, 2004 · 6 comments
Open

bug or wrong doc for 'foreach $lexical' #7224

p5pRT opened this issue Apr 9, 2004 · 6 comments

Comments

@p5pRT
Copy link

p5pRT commented Apr 9, 2004

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

Searchable as RT28396$

@p5pRT
Copy link
Author

p5pRT commented Apr 9, 2004

From @hfuru

Created by @hfuru

About `foreach $var (...)', the perlsyn manual page says,

  If the variable was previously declared with "my", it uses
  that variable instead of the global one,

That is not true. It creates a new lexical variable for the loop with
the same name as the outside variable, exactly as if one had written
`foreach my $var'. If it was the same variable, functions outside the
loop would see the loop variable, but they don't. They see the "my"
variable which was declared outside the loop. I suppose that's what you
mean with this addition to the above text​:

  but it's still localized to the loop.

but that does not really make sense. That sounds like the value of the
"outer" lexical variable would be saved, and restored after the loop.
That's how it works with non-lexical variables.

  my $var = "original value";
  foreach $var ("loop-value") {
  print "foreach​: $var, ";
  f();
  }
  print "end​: $var\n";
  sub f { print "function​: $var\n"; }
-->
  foreach​: loop-value, function​: original value
  end​: original value

BTW, I think this is a misfeature which should get a warning. If one
has such a loop which intends the variable to be global, inserting a
`my' previously in the code silently breaks the loop even though that
new `my' variable isn't actually used in the loop. And there is no need
for this feature since one can just say `foreach my $var' instead of
`foreach $var'.

Perl Info

Flags:
    category=docs
    severity=medium

Site configuration information for perl v5.8.0:

Configured by bhcompile at Wed Aug 13 11:45:59 EDT 2003.

Summary of my perl5 (revision 5.0 version 8 subversion 0) configuration:
  Platform:
    osname=linux, osvers=2.4.21-1.1931.2.382.entsmp, archname=i386-linux-thread-multi
    uname='linux stripples.devel.redhat.com 2.4.21-1.1931.2.382.entsmp #1 smp wed aug 6 17:18:52 edt 2003 i686 i686 i386 gnulinux '
    config_args='-des -Doptimize=-O2 -g -pipe -march=i386 -mcpu=i686 -Dmyhostname=localhost -Dperladmin=root@localhost -Dcc=gcc -Dcf_by=Red Hat, Inc. -Dinstallprefix=/usr -Dprefix=/usr -Darchname=i386-linux -Dvendorprefix=/usr -Dsiteprefix=/usr -Dotherlibdirs=/usr/lib/perl5/5.8.0 -Duseshrplib -Dusethreads -Duseithreads -Duselargefiles -Dd_dosuid -Dd_semctl_semun -Di_db -Ui_ndbm -Di_gdbm -Di_shadow -Di_syslog -Dman3ext=3pm -Duseperlio -Dinstallusrbinperl -Ubincompat5005 -Uversiononly -Dpager=/usr/bin/less -isr'
    hint=recommended, useposix=true, d_sigaction=define
    usethreads=define use5005threads=undef useithreads=define usemultiplicity=define
    useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
    use64bitint=undef use64bitall=undef uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='gcc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm',
    optimize='-O2 -g -pipe -march=i386 -mcpu=i686',
    cppflags='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -I/usr/include/gdbm'
    ccversion='', gccversion='3.2.2 20030222 (Red Hat Linux 3.2.2-5)', 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='gcc', ldflags =' -L/usr/local/lib'
    libpth=/usr/local/lib /lib /usr/lib
    libs=-lnsl -lgdbm -ldb -ldl -lm -lpthread -lc -lcrypt -lutil
    perllibs=-lnsl -ldl -lm -lpthread -lc -lcrypt -lutil
    libc=/lib/libc-2.3.2.so, so=so, useshrplib=true, libperl=libperl.so
    gnulibc_version='2.3.2'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-rdynamic -Wl,-rpath,/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE'
    cccdlflags='-fPIC', lddlflags='-shared -L/usr/local/lib'

Locally applied patches:
    MAINT18379


@INC for perl v5.8.0:
    /usr/lib/perl5/5.8.0/i386-linux-thread-multi
    /usr/lib/perl5/5.8.0
    /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi
    /usr/lib/perl5/site_perl/5.8.0
    /usr/lib/perl5/site_perl
    /usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi
    /usr/lib/perl5/vendor_perl/5.8.0
    /usr/lib/perl5/vendor_perl
    /usr/lib/perl5/5.8.0/i386-linux-thread-multi
    /usr/lib/perl5/5.8.0
    .


Environment for perl v5.8.0:
    HOME=/usit/saruman/gt-u1/hbf
    LANG (unset)
    LANGUAGE (unset)
    LC_CTYPE=no_NO
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/usr/bin:/usit/saruman/gt-u1/hbf/bin:/usit/saruman/gt-u1/hbf/bin/linux:/local/bin:/local/gnu/bin:/local/sbin:/usr/bin/X11:/usr/X11R6/bin:/usr/bin:/bin:/usr/games
    PERL_BADLANG (unset)
    SHELL=/local/gnu/bin/bash

@p5pRT
Copy link
Author

p5pRT commented Dec 18, 2011

From @jkeenan

On Thu Apr 08 21​:35​:31 2004, h.b.furuseth@​usit.uio.no wrote​:

About `foreach $var (...)', the perlsyn manual page says,

If the variable was previously declared with "my"\, it uses
that variable instead of the global one\,

That is not true. It creates a new lexical variable for the loop with
the same name as the outside variable, exactly as if one had written
`foreach my $var'. If it was the same variable, functions outside the
loop would see the loop variable, but they don't. They see the "my"
variable which was declared outside the loop. I suppose that's what
you
mean with this addition to the above text​:

but it's still localized to the loop\.

but that does not really make sense. That sounds like the value of
the
"outer" lexical variable would be saved, and restored after the loop.
That's how it works with non-lexical variables.

my $var = "original value";
foreach $var \("loop\-value"\) \{
    print "foreach​: $var\, ";
    f\(\);
\}
print "end​: $var\\n";
sub f \{ print "function​: $var\\n"; \}

-->
foreach​: loop-value, function​: original value
end​: original value

While reviewing older tickets, I have read this several times. Each
time I read it, I tend to believe it.

But then, when I go and read 'perldoc perlsyn' (the section on "Foreach
Loops"), I'm perfectly fine with what I read *there*. There's a final
sentence in that paragraph that helps clarify things for me​: "This
implicit localization occurs *only* in a 'foreach' loop."

So I don't think there's a bug here, and the current documentation makes
sense to me with respect to the poster's example above.

What do other people think?

Thank you very much.
Jim Keenan

BTW, I think this is a misfeature which should get a warning. If one
has such a loop which intends the variable to be global, inserting a
`my' previously in the code silently breaks the loop even though that
new `my' variable isn't actually used in the loop. And there is no
need
for this feature since one can just say `foreach my $var' instead of
`foreach $var'.

[Please do not change anything below this line]
-----------------------------------------------------------------
---
Flags​:
category=docs
severity=medium
---
Site configuration information for perl v5.8.0​:

Configured by bhcompile at Wed Aug 13 11​:45​:59 EDT 2003.

Summary of my perl5 (revision 5.0 version 8 subversion 0)
configuration​:
Platform​:
osname=linux, osvers=2.4.21-1.1931.2.382.entsmp, archname=i386-
linux-thread-multi
uname='linux stripples.devel.redhat.com 2.4.21-1.1931.2.382.entsmp
#1 smp wed aug 6 17​:18​:52 edt 2003 i686 i686 i386 gnulinux '
config_args='-des -Doptimize=-O2 -g -pipe -march=i386 -mcpu=i686
-Dmyhostname=localhost -Dperladmin=root@​localhost -Dcc=gcc
-Dcf_by=Red Hat, Inc. -Dinstallprefix=/usr -Dprefix=/usr
-Darchname=i386-linux -Dvendorprefix=/usr -Dsiteprefix=/usr
-Dotherlibdirs=/usr/lib/perl5/5.8.0 -Duseshrplib -Dusethreads
-Duseithreads -Duselargefiles -Dd_dosuid -Dd_semctl_semun -Di_db
-Ui_ndbm -Di_gdbm -Di_shadow -Di_syslog -Dman3ext=3pm -Duseperlio
-Dinstallusrbinperl -Ubincompat5005 -Uversiononly
-Dpager=/usr/bin/less -isr'
hint=recommended, useposix=true, d_sigaction=define
usethreads=define use5005threads=undef useithreads=define
usemultiplicity=define
useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
use64bitint=undef use64bitall=undef uselongdouble=undef
usemymalloc=n, bincompat5005=undef
Compiler​:
cc='gcc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS
-DDEBUGGING -fno-strict-aliasing -I/usr/local/include
-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm',
optimize='-O2 -g -pipe -march=i386 -mcpu=i686',
cppflags='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS
-DDEBUGGING -fno-strict-aliasing -I/usr/local/include
-I/usr/include/gdbm'
ccversion='', gccversion='3.2.2 20030222 (Red Hat Linux 3.2.2-5)',
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='gcc', ldflags =' -L/usr/local/lib'
libpth=/usr/local/lib /lib /usr/lib
libs=-lnsl -lgdbm -ldb -ldl -lm -lpthread -lc -lcrypt -lutil
perllibs=-lnsl -ldl -lm -lpthread -lc -lcrypt -lutil
libc=/lib/libc-2.3.2.so, so=so, useshrplib=true,
libperl=libperl.so
gnulibc_version='2.3.2'
Dynamic Linking​:
dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-
rdynamic
-Wl,-rpath,/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE'
cccdlflags='-fPIC', lddlflags='-shared -L/usr/local/lib'

Locally applied patches​:
MAINT18379

---
@​INC for perl v5.8.0​:
/usr/lib/perl5/5.8.0/i386-linux-thread-multi
/usr/lib/perl5/5.8.0
/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi
/usr/lib/perl5/site_perl/5.8.0
/usr/lib/perl5/site_perl
/usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi
/usr/lib/perl5/vendor_perl/5.8.0
/usr/lib/perl5/vendor_perl
/usr/lib/perl5/5.8.0/i386-linux-thread-multi
/usr/lib/perl5/5.8.0
.

---
Environment for perl v5.8.0​:
HOME=/usit/saruman/gt-u1/hbf
LANG (unset)
LANGUAGE (unset)
LC_CTYPE=no_NO
LD_LIBRARY_PATH (unset)
LOGDIR (unset)
PATH=/usr/bin​:/usit/saruman/gt-u1/hbf/bin​:/usit/saruman/gt-

u1/hbf/bin/linux​:/local/bin​:/local/gnu/bin​:/local/sbin​:/usr/bin/X11​:/usr/X11R6/bin​:/usr/bin​:/bin​:/usr/games

PERL\_BADLANG \(unset\)
SHELL=/local/gnu/bin/bash

@p5pRT
Copy link
Author

p5pRT commented Dec 18, 2011

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

@p5pRT
Copy link
Author

p5pRT commented Dec 18, 2011

From @cpansprout

On Sat Dec 17 20​:02​:40 2011, jkeenan wrote​:

On Thu Apr 08 21​:35​:31 2004, h.b.furuseth@​usit.uio.no wrote​:

About `foreach $var (...)', the perlsyn manual page says,

If the variable was previously declared with "my"\, it uses
that variable instead of the global one\,

That is not true. It creates a new lexical variable for the loop
with
the same name as the outside variable, exactly as if one had written
`foreach my $var'. If it was the same variable, functions outside
the
loop would see the loop variable, but they don't. They see the "my"
variable which was declared outside the loop. I suppose that's what
you
mean with this addition to the above text​:

but it's still localized to the loop\.

but that does not really make sense. That sounds like the value of
the
"outer" lexical variable would be saved, and restored after the
loop.
That's how it works with non-lexical variables.

my $var = "original value";
foreach $var \("loop\-value"\) \{
    print "foreach​: $var\, ";
    f\(\);
\}
print "end​: $var\\n";
sub f \{ print "function​: $var\\n"; \}

-->
foreach​: loop-value, function​: original value
end​: original value

While reviewing older tickets, I have read this several times. Each
time I read it, I tend to believe it.

But then, when I go and read 'perldoc perlsyn' (the section on
"Foreach
Loops"), I'm perfectly fine with what I read *there*. There's a final
sentence in that paragraph that helps clarify things for me​: "This
implicit localization occurs *only* in a 'foreach' loop."

So I don't think there's a bug here, and the current documentation
makes
sense to me with respect to the poster's example above.

What do other people think?

I think this is a can of worms I don’t want to open. :-(

It makes me wonder​: If we introduce lexical aliases through lvalue
references, then which $x will the function see?

my $x = 3; my $y = 4;
my $func = sub { print "$x\n"; };
\$x = \$y;
&$func;

I think the original poster has a point. This doesn’t do what the
documentation says​:

$ perl5.15.5 -le 'my $x = 3; my $sub = sub { print $x }; for $x (4){&$sub}'
3

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Dec 18, 2011

From @cpansprout

On Sat Dec 17 23​:14​:17 2011, sprout wrote​:

I think the original poster has a point. This doesn’t do what the
documentation says​:

$ perl5.15.5 -le 'my $x = 3; my $sub = sub { print $x }; for $x
(4){&$sub}'
3

It works for our variables​:

perl -le 'our $x; $sub = sub { print $x }; for $x(4) { &$sub }'
4

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Dec 18, 2011

From @druud62

On 2011-12-18 05​:02, James E Keenan via RT wrote​:

But then, when I go and read 'perldoc perlsyn' (the section on "Foreach
Loops"), I'm perfectly fine with what I read *there*. There's a final
sentence in that paragraph that helps clarify things for me​: "This
implicit localization occurs *only* in a 'foreach' loop."

So I don't think there's a bug here, and the current documentation makes
sense to me with respect to the poster's example above.

What do other people think?

I don't like the implicit localization.

perl -wle '
  my $i = 42;
  for $i ( 1 .. 2 ) { print $i }
  print $i;
'
1
2
42

I consider this magic-for-magic-only​:

perl -wle '
  $_ = 0;
  print;
  for ( 1 .. 2 ) { print }
  print;
  print for 3 .. 4;
  print;
'
0
1
2
0
3
4
0

(ok, not for magic only, good (and bad) for golfing too)

--
Ruud

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants