Front page | perl.perl5.porters |
Postings from August 2009
[perl #68816] RE match variable scope
Thread Next
From:
perlbug-followup
Date:
August 27, 2009 01:15
Subject:
[perl #68816] RE match variable scope
Message ID:
rt-3.6.HEAD-2466-1251360575-725.68816-75-0@perl.org
# New Ticket Created by ian.goodacre@xtra.co.nz
# Please include the string: [perl #68816]
# in the subject line of all future correspondence about this issue.
# <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=68816 >
This is a bug report for perl from ian@alula.home.local,
generated with the help of perlbug 1.36 running under perl 5.10.0.
-----------------------------------------------------------------
[Pleas enter your report here]
perlre says:
The numbered match variables ($1, $2, $3, etc.) and the related
punctuation set ($+, $&, "$`", "$'", and $^N) are all dynamically
scoped until the end of the enclosing block or until the next
successful match, whichever comes first. (See "Compound
Statements" in
perlsyn.)
NOTE: Failed matches in Perl do not reset the match variables, which
makes it easier to write code that tests for a series of more
specific
cases and remembers the best match.
In a foreach loop I expect that the BLOCK is entered, executed and
exited once
in each iteration of the loop (with the possible exception of the redo loop
control command, which should be better defined to specify whether it causes
scope exit and entry).
Thus I expect that numbered match variables created within a loop BLOCK
go out
of scope at the end of the iteration in which they were defined. If there is
no match in an iteration, I expect the loop variables will not be defined,
in which case it is ambiguous and should be documented whether dynamically
scoped numbered match variables defined in an outer scope are masked or not.
In the following, I expect '1' to be printed only in the first iteration
$ perl -wle 'for(1..3){/(1)/; print $1 // "undef"}'
1
1
1
I expect the presence of an empty continue block not to make any difference,
but in fact it does - it corrects the behavior.
$ perl -wle 'for(1..3){/(1)/; print $1 // "undef"}continue{}'
1
undef
undef
Consider also:
my $_ = '1';
/(.)/;
print "before: \$1 = $1\n";
for (2..4) {
print "\$_ = $_\n";
print "first: \$1 = $1\n";
/(3)/;
print "second: \$1 = $1\n";
}
print "after: \$1 = $1\n";
Which produces
before: $1 = 1
$_ = 2
first: $1 = 1
second: $1 = 1
$_ = 3
first: $1 = 1
second: $1 = 3
$_ = 4
first: $1 = 3
second: $1 = 3
after: $1 = 1
The $1 of the outer scope is visible within the loop BLOCK until the
successful
match in the second iteration, after which the $1 of the outer scope is
masked.
But the inner scope $1 continues to mask the outer scope $1 throughout
the third
iteration, as if it didn't go out of scope when execution of the loop
BLOCK was
completed at the end of the second iteration.
Note that the $1 of the outer scope does exist separately and is not merely
overwritten by the match within the loop. After the loop is finished it
still
has its proper value.
Again, adding an empty continue BLOCK results in correct behavior:
my $_ = '1';
/(.)/;
print "before: \$1 = $1\n";
for (2..4) {
print "\$_ = $_\n";
print "first: \$1 = $1\n";
/(3)/;
print "second: \$1 = $1\n";
} continue {}
print "after: \$1 = $1\n";
produces
before: $1 = 1
$_ = 2
first: $1 = 1
second: $1 = 1
$_ = 3
first: $1 = 1
second: $1 = 3
$_ = 4
first: $1 = 1
second: $1 = 1
after: $1 = 1
Compare this also with
my $var = "outer";
print "before: $var\n";
for (1..3) {
print "first: $var\n";
my $var = "inner $_" if(/2/);
print "second: $var\n";
}
print "after: $var\n";
which produces
before: outer
first: outer
second:
first: outer
second: inner 2
first: outer
second:
after: outer
In this case, as expected, the dynamically scoped $var of the inner scope
doesn't mask that of the outer scope before it is declared and the value
of the $var of the inner scope does not persist from one iteration to
the next even if the runtime effect of the initialization is prevented
by a conditional.
I think it would be better if the number match variables from a match
within a loop BLOCK behaved as they do when that loop has an
empty continue BLOCK.
If there is a reason not to change this behavior then the behavior and
the reason for it should be prominently documented.
[Please do not change anything below this line]
-----------------------------------------------------------------
---
Flags:
category=core
severity=low
---
Site configuration information for perl 5.10.0:
Configured by ian at Sat Jul 18 17:25:15 NZST 2009.
Summary of my perl5 (revision 5 version 10 subversion 0) configuration:
Platform:
osname=linux, osvers=2.6.18-92.el5, archname=i686-linux-thread-multi
uname='linux alula.home.local 2.6.18-92.el5 #1 smp tue jun 10
18:49:47 edt 2008 i686 i686 i386 gnulinux '
config_args=''
hint=previous, useposix=true, d_sigaction=define
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='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing
-pipe -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
-I/usr/include/gdbm',
optimize='-O2',
cppflags='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe
-I/usr/local/include -I/usr/include/gdbm -D_REENTRANT -D_GNU_SOURCE
-fno-strict-aliasing -pipe -I/usr/local/include -D_LARGEFILE_SOURCE
-D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm'
ccversion='', gccversion='4.1.2 20080704 (Red Hat 4.1.2-44)',
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 -lgdbm -ldb -ldl -lm -lcrypt -lutil -lpthread -lc
perllibs=-lnsl -ldl -lm -lcrypt -lutil -lpthread -lc
libc=/lib/libc-2.5.so, so=so, useshrplib=false, libperl=libperl.a
gnulibc_version='2.5'
Dynamic Linking:
dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
cccdlflags='-fPIC', lddlflags='-shared -O2 -L/usr/local/lib'
Locally applied patches:
---
@INC for perl 5.10.0:
/usr/local/lib/perl5/5.10.0/i686-linux-thread-multi
/usr/local/lib/perl5/5.10.0
/usr/local/lib/perl5/site_perl/5.10.0/i686-linux-thread-multi
/usr/local/lib/perl5/site_perl/5.10.0
.
---
Environment for perl 5.10.0:
HOME=/home/ian
LANG=en_NZ.UTF-8
LANGUAGE (unset)
LD_LIBRARY_PATH (unset)
LOGDIR (unset)
PATH=/usr/local/java/jdk/bin:/usr/local/java/ant/bin:/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/Trolltech/Qt-4.4.3/bin:/home/ian/bin:/sbin
PERLDOC_PAGER=less
PERL_BADLANG (unset)
SHELL=/bin/bash
Thread Next
-
[perl #68816] RE match variable scope
by perlbug-followup