Velocity Reviews > Perl > Recursion and \${*digit*} variables

# Recursion and \${*digit*} variables

Mark
Guest
Posts: n/a

 08-14-2009
It appears that new \${*digit*} variables are not created when the same
subroutine is re-entered. Is this to be expected?

use strict ;
use warnings;

my \$line = 'abc';
doit();
exit;

sub doit {
# local(\$1); # adding this doesn't appear to have an effect
\$line =~ /(.)/ || die "no match";
print "bef \\$1 =\$1\n";

\$line = substr(\$line,1);
doit() if length(\$line);

my \$thing = \$1; # WRONG! \$1 has been changed by recursive call to
doit()

print "aft \\$1 =\$1\n";
}

Output:
bef \$1 =a
bef \$1 =b
bef \$1 =c
aft \$1 =c
aft \$1 =c
aft \$1 =c

Expected output:
bef \$1 =a
bef \$1 =b
bef \$1 =c
aft \$1 =c
aft \$1 =b
aft \$1 =a

C.DeRykus
Guest
Posts: n/a

 08-14-2009
On Aug 14, 11:49*am, Mark <(E-Mail Removed)> wrote:
> It appears that new \${*digit*} variables are not created when the same
> subroutine is re-entered. *Is this to be expected?
>
> use strict ;
> use warnings;
>
> my \$line = 'abc';
> doit();
> exit;
>
> sub doit {
> # * local(\$1); *# adding this doesn't appear to have an effect
> * * \$line =~ /(.)/ || die "no match";
> * * print "bef \\$1 *=\$1\n";
>
> * * \$line = substr(\$line,1);
> * * doit() if length(\$line);
>
> * * my \$thing = \$1; # WRONG! \$1 has been changed by recursive call to
> doit()
>
> * * print "aft \\$1 *=\$1\n";
>
> }
>
> Output:
> bef \$1 *=a
> bef \$1 *=b
> bef \$1 *=c
> aft \$1 *=c
> aft \$1 *=c
> aft \$1 *=c
>
> Expected output:
> bef \$1 *=a
> bef \$1 *=b
> bef \$1 *=c
> aft \$1 *=c
> aft \$1 *=b
> aft \$1 *=a

No, this came up in a recent thread. Even if a match fails
within a given scope, a previously successful backref isn't
cleared:

my \$s='a';
for (1..2){
print \$s=~/(.)/ ? "match:\$1" : "no match:\$1";
\$s=substr(\$s,1);
}
__END__

match:a
no match:a

--
Charles DeRykus

Mark
Guest
Posts: n/a

 08-14-2009

> I would expect any sub call (that performed a successful match) to
> clobber \$N. Is that not the case?

No, I don't believe that is the case. When I remove the recursion, it
works as I expect, the local \$N retains its value.
For example:

use strict ;
use warnings;

my \$line = 'abc';

doit();

exit;

sub doit {
\$line =~ /(.)/ || die "no match";
print "bef1 \\$1 =\$1\n";

\$line = substr(\$line,1);
doit2() if length(\$line);

print "aft1 \\$1 =\$1\n";
}

sub doit2 {
\$line =~ /(.)/ || die "no match";
print "bef2 \\$1 =\$1\n";

\$line = substr(\$line,1);

print "aft2 \\$1 =\$1\n";
}

Output:
bef1 \$1 =a
bef2 \$1 =b
aft2 \$1 =b
aft1 \$1 =a

C.DeRykus
Guest
Posts: n/a

 08-14-2009
On Aug 14, 2:46*pm, "C.DeRykus" <(E-Mail Removed)> wrote:
> On Aug 14, 11:49*am, Mark <(E-Mail Removed)> wrote:
>
>
>
> > It appears that new \${*digit*} variables are not created when the same
> > subroutine is re-entered. *Is this to be expected?

>
> > use strict ;
> > use warnings;

>
> > my \$line = 'abc';
> > doit();
> > exit;

>
> > sub doit {
> > # * local(\$1); *# adding this doesn't appear to have an effect
> > * * \$line =~ /(.)/ || die "no match";
> > * * print "bef \\$1 *=\$1\n";

>
> > * * \$line = substr(\$line,1);
> > * * doit() if length(\$line);

>
> > * * my \$thing = \$1; # WRONG! \$1 has been changed by recursive call to
> > doit()

>
> > * * print "aft \\$1 *=\$1\n";

>
> > }

>
> > Output:
> > bef \$1 *=a
> > bef \$1 *=b
> > bef \$1 *=c
> > aft \$1 *=c
> > aft \$1 *=c
> > aft \$1 *=c

>
> > Expected output:
> > bef \$1 *=a
> > bef \$1 *=b
> > bef \$1 *=c
> > aft \$1 *=c
> > aft \$1 *=b
> > aft \$1 *=a

>
> No, this came up in a recent thread. Even if a match fails
> within a given scope, a previously successful backref isn't
> cleared:
>
> my \$s='a';
> for (1..2){
> * print \$s=~/(.)/ ? "match:\$1" : "no match:\$1";
> * \$s=substr(\$s,1);}
>
> __END__
>
> match:a
> no match:a

Just to expand that explanation a bit more:

sub doit {
\$line =~ /(.)/ || die "no match";

print "bef \\$1 =\$1\n"; # matches succeed initially
\$line = substr(\$line,1); # as \$line gets emptied
doit() if length(\$line); # and doit() recurses
my \$thing = \$1; # WRONG! ..

print "aft \\$1 =\$1\n";
}

By the time the recursion starts to unwind, \$line has
been drained and the match fails. Because the final "c"
matched successfully though, \$1 doesn't get cleared.
So you see the trailing series of "c" printed.

--
Charles DeRykus

C.DeRykus
Guest
Posts: n/a

 08-14-2009
On Aug 14, 4:17*pm, "C.DeRykus" <(E-Mail Removed)> wrote:
> On Aug 14, 2:46*pm, "C.DeRykus" <(E-Mail Removed)> wrote:
>
>
>
> > On Aug 14, 11:49*am, Mark <(E-Mail Removed)> wrote:

>
> > > It appears that new \${*digit*} variables are not created when the same
> > > subroutine is re-entered. *Is this to be expected?

>
> > > use strict ;
> > > use warnings;

>
> > > my \$line = 'abc';
> > > doit();
> > > exit;

>
> > > sub doit {
> > > # * local(\$1); *# adding this doesn't appear to have an effect
> > > * * \$line =~ /(.)/ || die "no match";
> > > * * print "bef \\$1 *=\$1\n";

>
> > > * * \$line = substr(\$line,1);
> > > * * doit() if length(\$line);

>
> > > * * my \$thing = \$1; # WRONG! \$1 has been changed by recursive call to
> > > doit()

>
> > > * * print "aft \\$1 *=\$1\n";

>
> > > }

>
> > > Output:
> > > bef \$1 *=a
> > > bef \$1 *=b
> > > bef \$1 *=c
> > > aft \$1 *=c
> > > aft \$1 *=c
> > > aft \$1 *=c

>
> > > Expected output:
> > > bef \$1 *=a
> > > bef \$1 *=b
> > > bef \$1 *=c
> > > aft \$1 *=c
> > > aft \$1 *=b
> > > aft \$1 *=a

>
> > No, this came up in a recent thread. Even if a match fails
> > within a given scope, a previously successful backref isn't
> > cleared:

>
> > my \$s='a';
> > for (1..2){
> > * print \$s=~/(.)/ ? "match:\$1" : "no match:\$1";
> > * \$s=substr(\$s,1);}

>
> > __END__

>
> > match:a
> > no match:a

>
> Just to expand that explanation a bit more:
>
> sub doit {
> * \$line =~ /(.)/ || die "no match";
>
> * print "bef \\$1 *=\$1\n"; * *# matches succeed initially
> * \$line = substr(\$line,1); * # as \$line gets emptied
> * doit() if length(\$line); * # and doit() recurses
> * my \$thing = \$1; # WRONG! ..
>
> * print "aft \\$1 *=\$1\n";
>
> }
>
> By the time the recursion starts to unwind, \$line has
> been drained and the match fails. Because the final "c"
> matched successfully though, \$1 doesn't get cleared.
> So you see the trailing series of "c" printed.
>

No. I need to rethink that...

--
Charles DeRykus

C.DeRykus
Guest
Posts: n/a

 08-15-2009
On Aug 14, 4:10*pm, Mark <(E-Mail Removed)> wrote:
> > I would expect any sub call (that performed a successful match) to
> > clobber \$N. Is that not the case?

>
> No, I don't believe that is the case. *When I remove the recursion, it
> works as I expect, the local \$N retains its value.
> For example:
>
> use strict ;
> use warnings;
>
> my \$line = 'abc';
>
> doit();
>
> exit;
>
> sub doit {
> * * \$line =~ /(.)/ || die "no match";
> * * print "bef1 \\$1 *=\$1\n";
>
> * * \$line = substr(\$line,1);
> * * doit2() if length(\$line);
>
> * * print "aft1 \\$1 *=\$1\n";
>
> }
>
> sub doit2 {
> * * \$line =~ /(.)/ || die "no match";
> * * print "bef2 \\$1 *=\$1\n";
>
> * * \$line = substr(\$line,1);
>
> * * print "aft2 \\$1 *=\$1\n";
>
> }
>
> Output:
> bef1 \$1 *=a
> bef2 \$1 *=b
> aft2 \$1 *=b
> aft1 \$1 *=a

Hopefully I'm not mis-firing again but doit2() would introduce
a new scope with its own set of \$N matches which won't be affected
by successful matches in other scopes. But in doit()'s scope,
successful \$N matches self-clobber as mentioned.

--
Charles DeRykus

sln@netherlands.com
Guest
Posts: n/a

 08-15-2009
On Fri, 14 Aug 2009 11:49:39 -0700 (PDT), Mark <(E-Mail Removed)> wrote:

>It appears that new \${*digit*} variables are not created when the same
>subroutine is re-entered. Is this to be expected?
>
>use strict ;
>use warnings;
>
>my \$line = 'abc';
>doit();
>exit;
>
>sub doit {
># local(\$1); # adding this doesn't appear to have an effect
> \$line =~ /(.)/ || die "no match";
> print "bef \\$1 =\$1\n";
>
> \$line = substr(\$line,1);
> doit() if length(\$line);
>
> my \$thing = \$1; # WRONG! \$1 has been changed by recursive call to
>doit()
>
> print "aft \\$1 =\$1\n";
>}
>
>
>Output:
>bef \$1 =a
>bef \$1 =b
>bef \$1 =c
>aft \$1 =c
>aft \$1 =c
>aft \$1 =c
>
>Expected output:
>bef \$1 =a
>bef \$1 =b
>bef \$1 =c
>aft \$1 =c
>aft \$1 =b
>aft \$1 =a

Apparently there is only 1 set of N vars per scope,
looks like its set at compile time.

So you can't stack them in the way of a recursion.
This seems to hold down memory consumption and the cost
of state.

Usually, when you recurse a function, everything starts a new.
A new regular expression evaluation and gleaning results.
In that scope, the last N vars are retained, the results aren't
stacked.

The results you obtained are not faulty, nor the result of a bad match.
The last state of N vars were retained when the stack unwound.

Remember, 1 scope, 1 set of N vars.
Poor example follows.

-sln

================================================== ====
Output:

sub b - before = b
sub c - before = c
sub d - before = d
sub e - before = e(e)
sub d - before = d
sub e - before = f(f)
sub d - before = d
sub e - before = g(g)
sub d - before = d
sub e - before = h(h)

sub e - after = h(h)
sub d - after = d
sub e - after = h(g)
sub d - after = d
sub e - after = h(f)
sub d - after = d
sub e - after = h(e)
sub d - after = d
sub c - after = c
sub b - after = b

================================================== ======

use strict ;
use warnings;
my \$cnt = 0;

my \$regx = qr/(.)/;

\$cnt = 0;
my \$Estr = 'e';
b();

sub b
{
my \$str = 'b';
\$str =~ /\$regx/;
print "sub b - before = \$1\n";
c();
print "sub b - after = \$1\n";
}

sub c
{
my \$str = 'c';
\$str =~ /\$regx/;
print "sub c - before = \$1\n";
d();
print "sub c - after = \$1\n";
}

sub d
{
my \$str = 'd';
\$str =~ /\$regx/;
print "sub d - before = \$1\n";
e();
print "sub d - after = \$1\n";
}

sub e
{
++\$Estr if (++\$cnt > 1);

\$Estr =~ /\$regx/;
my \$tmp = \$1;

print "sub e - before = \$1(\$tmp)\n";

print "\n" if (\$cnt >= 4);
d() if (\$cnt < 4);
print "sub e - after = \$1(\$tmp)\n";

}

sln@netherlands.com
Guest
Posts: n/a

 08-15-2009
On Fri, 14 Aug 2009 16:17:32 -0700 (PDT), "C.DeRykus" <(E-Mail Removed)> wrote:

>On Aug 14, 2:46*pm, "C.DeRykus" <(E-Mail Removed)> wrote:
>> On Aug 14, 11:49*am, Mark <(E-Mail Removed)> wrote:
>>
>>
>>
>> > It appears that new \${*digit*} variables are not created when the same
>> > subroutine is re-entered. *Is this to be expected?

>>
>> > use strict ;
>> > use warnings;

>>
>> > my \$line = 'abc';
>> > doit();
>> > exit;

>>
>> > sub doit {
>> > # * local(\$1); *# adding this doesn't appear to have an effect
>> > * * \$line =~ /(.)/ || die "no match";
>> > * * print "bef \\$1 *=\$1\n";

>>
>> > * * \$line = substr(\$line,1);
>> > * * doit() if length(\$line);

>>
>> > * * my \$thing = \$1; # WRONG! \$1 has been changed by recursive call to
>> > doit()

>>
>> > * * print "aft \\$1 *=\$1\n";

>>
>> > }

>>
>> > Output:
>> > bef \$1 *=a
>> > bef \$1 *=b
>> > bef \$1 *=c
>> > aft \$1 *=c
>> > aft \$1 *=c
>> > aft \$1 *=c

>>
>> > Expected output:
>> > bef \$1 *=a
>> > bef \$1 *=b
>> > bef \$1 *=c
>> > aft \$1 *=c
>> > aft \$1 *=b
>> > aft \$1 *=a

>>
>> No, this came up in a recent thread. Even if a match fails
>> within a given scope, a previously successful backref isn't
>> cleared:
>>
>> my \$s='a';
>> for (1..2){
>> * print \$s=~/(.)/ ? "match:\$1" : "no match:\$1";
>> * \$s=substr(\$s,1);}
>>
>> __END__
>>
>> match:a
>> no match:a

>
>
>Just to expand that explanation a bit more:
>
>sub doit {
> \$line =~ /(.)/ || die "no match";
>
> print "bef \\$1 =\$1\n"; # matches succeed initially
> \$line = substr(\$line,1); # as \$line gets emptied
> doit() if length(\$line); # and doit() recurses
> my \$thing = \$1; # WRONG! ..
>
> print "aft \\$1 =\$1\n";
>}
>
>By the time the recursion starts to unwind, \$line has
>been drained and the match fails. Because the final "c"
>matched successfully though, \$1 doesn't get cleared.
>So you see the trailing series of "c" printed.

Matching had nothing to do with why his \$1 contained 'c'
when the stack unwound.

The reason is he keeps reenterring the same scope block.
In terms of N vars, there is only one scope block so
the N vars keep thier last state.

N var state is not stacked, it only has scope.

-sln

sln@netherlands.com
Guest
Posts: n/a

 08-15-2009
On Fri, 14 Aug 2009 18:30:51 -0700, http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:

>On Fri, 14 Aug 2009 16:17:32 -0700 (PDT), "C.DeRykus" <(E-Mail Removed)> wrote:
>
>>On Aug 14, 2:46*pm, "C.DeRykus" <(E-Mail Removed)> wrote:
>>> On Aug 14, 11:49*am, Mark <(E-Mail Removed)> wrote:
>>>
>>>
>>>
>>> > It appears that new \${*digit*} variables are not created when the same
>>> > subroutine is re-entered. *Is this to be expected?
>>>
>>> > use strict ;
>>> > use warnings;
>>>
>>> > my \$line = 'abc';
>>> > doit();
>>> > exit;
>>>
>>> > sub doit {
>>> > # * local(\$1); *# adding this doesn't appear to have an effect
>>> > * * \$line =~ /(.)/ || die "no match";
>>> > * * print "bef \\$1 *=\$1\n";
>>>
>>> > * * \$line = substr(\$line,1);
>>> > * * doit() if length(\$line);
>>>
>>> > * * my \$thing = \$1; # WRONG! \$1 has been changed by recursive call to
>>> > doit()
>>>
>>> > * * print "aft \\$1 *=\$1\n";
>>>
>>> > }
>>>
>>> > Output:
>>> > bef \$1 *=a
>>> > bef \$1 *=b
>>> > bef \$1 *=c
>>> > aft \$1 *=c
>>> > aft \$1 *=c
>>> > aft \$1 *=c
>>>
>>> > Expected output:
>>> > bef \$1 *=a
>>> > bef \$1 *=b
>>> > bef \$1 *=c
>>> > aft \$1 *=c
>>> > aft \$1 *=b
>>> > aft \$1 *=a
>>>
>>> No, this came up in a recent thread. Even if a match fails
>>> within a given scope, a previously successful backref isn't
>>> cleared:
>>>
>>> my \$s='a';
>>> for (1..2){
>>> * print \$s=~/(.)/ ? "match:\$1" : "no match:\$1";
>>> * \$s=substr(\$s,1);}
>>>
>>> __END__
>>>
>>> match:a
>>> no match:a

>>
>>
>>Just to expand that explanation a bit more:
>>
>>sub doit {
>> \$line =~ /(.)/ || die "no match";
>>
>> print "bef \\$1 =\$1\n"; # matches succeed initially
>> \$line = substr(\$line,1); # as \$line gets emptied
>> doit() if length(\$line); # and doit() recurses
>> my \$thing = \$1; # WRONG! ..
>>
>> print "aft \\$1 =\$1\n";
>>}
>>
>>By the time the recursion starts to unwind, \$line has
>>been drained and the match fails. Because the final "c"
>>matched successfully though, \$1 doesn't get cleared.
>>So you see the trailing series of "c" printed.

>
>Matching had nothing to do with why his \$1 contained 'c'
>when the stack unwound.
>
>The reason is he keeps reenterring the same scope block.
>In terms of N vars, there is only one scope block so
>the N vars keep thier last state.
>
>N var state is not stacked, it only has scope.
>
>-sln

Aparently, for the N vars, the scope remained the same, it
never left. Kind of makes sense.
-sln

Nathan Keel
Guest
Posts: n/a

 08-15-2009
(E-Mail Removed) wrote:

> Aparently, for the N vars, the scope remained the same, it
> never left. Kind of makes sense.
> -sln

Apparently you forgot how to snip huge quotes for a few word reply.