Loop consuming my list

M

Marc Girod

Hello,

I was surprised to see in my own code, a difference between
the two lines (out of context...):

$self->rmhlink($type, $_) for @pl;
and:
for my $p (@pl) { $self->rmhlink($type, $p) }

The former consumed the contents of @pl.
The latter did not.

The rmhlink (member) function reads its arguments from @_,
and returns a value, often undef.

I tried to reproduce the case naively, but failed:

$ perl -wle '@s=qw(a b c);sub f{return};f($_)for@s;map{print $_}@s'
a
b
c

Is there thus an interaction from the package?

I cannot get this either...

$ perl -wle 'package Foo;@s=qw(a b c);sub new{$t=shift;$s={};bless $s,
$t}sub foo{return};$f=new Foo;$f->foo($_)for@s;map{print $_}@s'
a
b
c

I am afraid this is a symptom that I missed something fundamental...
Who is eating my list?

Thanks,
Marc
 
P

Peter Makholm

Marc Girod said:
Hello,

I was surprised to see in my own code, a difference between
the two lines (out of context...):

$self->rmhlink($type, $_) for @pl;
and:
for my $p (@pl) { $self->rmhlink($type, $p) }

The former consumed the contents of @pl.
The latter did not.

You probably have to defined what you mean by 'consumed the contents
of @pl'. I assume that you mean that the content of @pl has changed
somehow. The problme is that the first construction makes $_ an alias
to the elements in @pl and that $_ is a global variable.

In perl 5.10 you can make $_ a lexical variable by adding a 'my $_;'
somewhere in scope befor the loop:

my $_;
$self->rmhlink($type, $_) for @pl;

For older perls you have to localize $_ in your rmhlink method. I
would probably do both.

See also:
http://peter.makholm.net/2009/06/24/the-evil-of-a-global-_/

//Makholm
 
M

Marc Girod

Thank you Peter,

You probably have to defined what you mean by 'consumed the contents
of @pl'.

Indeed. In this case, the list was empty after running the loop.
The problem is that the first construction makes $_ an alias
to the elements in @pl and that $_ is a global variable.

That's what I didn't understand.
I thought it was lexical...
In perl 5.10 you can make $_ a lexical variable by adding a 'my $_;'
somewhere in scope befor the loop:

Thanks. I can now see that it is what I did, without the
side-effect of the name.

Excellent.
I *did* miss something important.

Marc
 
M

Marc Girod

It is not possible to change array size by manipulating $_.

Sorry, you are correct. The items were set to ''.
I tried the advice on 5.8.8, and checked that I cannot
make $_ lexical there, but that local $_ within rmhlink
works.

I believe that I'll be happy with the insight, and with
lexicalizing by naming as I did.

Thanks,
Marc
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top