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

RE match variable scope #9855

Open
p5pRT opened this issue Aug 27, 2009 · 4 comments
Open

RE match variable scope #9855

p5pRT opened this issue Aug 27, 2009 · 4 comments

Comments

@p5pRT
Copy link

p5pRT commented Aug 27, 2009

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

Searchable as RT68816$

@p5pRT
Copy link
Author

p5pRT commented Aug 27, 2009

From @ig3

Created by ian@alula.home.local

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.

Perl Info

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


@p5pRT
Copy link
Author

p5pRT commented Aug 27, 2009

From @demerphq

2009/8/27 ian.goodacre@​xtra.co.nz (via RT) <perlbug-followup@​perl.org>​:

If there is a reason not to change this behavior then the behavior and
the reason for it should be prominently documented.

Leaving aside the technicalities involved, would you feel that this is
a bad choice to take?

In other words, given that "fixing" this behaviour would probably
break /something/, yet clearly it is not in agreement wit the
documentation (i think because of optimisations) do you see any
serious problem with leaving it?

Im curious as to how people view the trade offs involved here.

Yves

--
perl -Mre=debug -e "/just|another|perl|hacker/"

@p5pRT
Copy link
Author

p5pRT commented Aug 27, 2009

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

@p5pRT
Copy link
Author

p5pRT commented Aug 27, 2009

From @ig3

demerphq wrote​:

2009/8/27 ian.goodacre@​xtra.co.nz (via RT) <perlbug-followup@​perl.org>​:

If there is a reason not to change this behavior then the behavior and
the reason for it should be prominently documented.

Leaving aside the technicalities involved, would you feel that this is
a bad choice to take?

In other words, given that "fixing" this behaviour would probably
break /something/, yet clearly it is not in agreement wit the
documentation (i think because of optimisations) do you see any
serious problem with leaving it?

Im curious as to how people view the trade offs involved here.

Yves

I would probably leave the behavior as it is for two reasons​:

1) Existing code might depend on it being as it is and I would break
such code only with great reluctance

2) For the same reason that a failed match doesn't reset the numbered
match variables (as described in perlre)

Not because I like the way that it is. The rare cases where the
persistence was valuable would probably be much clearer and less
vulnerable (e.g. to a continue block being added to the loop) if the
persistence were provided explicitly.

Ian

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