Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

I should've known better!

by ack (Deacon)
on Sep 10, 2009 at 18:03 UTC ( [id://794638]=perlmeditation: print w/replies, xml ) Need Help??

Well, I am red-faced with embarassment. Having worked around Perl for several years, I found one of those "traps" that must frustrate "newbies" but that I should've seen coming given my time with Perl.

A construct that I (and I suspect otheres) have used is the following:

foreach my $line (@text){ chomp($line); next if($line =~ /^\s*#/); #...do something with the non-commented lines }

The surprise was not in the basic construct, but rather that I forgot that $line is just an alias for each of the actual elements in the array @text. Of course the array could be anything (doesn't have to be text) and the processing in the loop could be anything.

The important thing is that anything (e.g., chomp($line) in this case) that alters the loop variable (e.g., $line) is actually operating on and affecting the actual values in the array.

Plenty of documentation reminds (and even warns us) of that fact...but I am almost continually forgetting it. I am amazed that this doesn't bit me more frequently...maybe if it did, I'd do a better job of remembering it...he says with a wry grin.

It just now bit me on a little test case I had quickly coded up as I looked at one of the Q&A's about 'arrays' when I went to print out the value of @text after processing it in the above loop and then push()'ing the result into an ouput array which I then went on to print out for comparison.

Much to my dismay, when I printed out @text after the loop I found that all of the new-lines were gone!

I had to stop and fret over it and then I remembered! In chomp()'ing the loop variable, I was actually chomping the array's member! Duhhh! Well, color me 'embarassed'!

I think it is really powerful that the loop variable is an alias and I have actually used that to good advantage in several instnaces. But it must be really mysterious to those new to Perl that using common constructs like the comment-removal code I showed above can result in some pretty mysterious behavior.

Just an observation regarding the power and, sometimes, mystery of Perl.

ack Albuquerque, NM

Replies are listed 'Best First'.
Re: I should've known better!
by TimToady (Parson) on Sep 11, 2009 at 02:26 UTC
    Yes, well, I should have known better too. :-)

    In fact, in Perl 6, the equivalent loop:

    for @text -> $line { ... }
    makes $line a read-only alias to catch just this sort of mixup. You'd write:
    for @text <-> $line { ... }
    (note the double-ended arrow) to get the read-write semantics. But it's not the default. Perl 6 is all about picking sane defaults while not preventing you from doing the sorts of powerful things you can do in Perl 5.

      In Perl 5 my $var; ... for $var (...) {...} doesn't alter the contents of the $var global to the for loop. Is that true for both the -> and <-> variants of the Perl 6 for loop illustrated above?

      I presume you can for @array <-> my $var {...} in Perl 6 to make the scope of $var obvious.


      True laziness is hard work
        In Perl 5 my $var; ... for $var (...) {...} doesn't alter the contents of the $var global to the for loop. Is that true for both the -> and <-> variants of the Perl 6 for loop illustrated above?
        Yes.
        presume you can for @array <-> my $var {...}, in Perl 6 to make the scope of $var obvious.
        No, you can't. Both arrows actually introduce a signature, and my in a signature doesn't make sense.

        I used to write -> my $x too, but got used to omitting the my rather quickly :-).

        Perl 6 - links to (nearly) everything that is Perl 6.
Re: I should've known better!
by vitoco (Hermit) on Sep 10, 2009 at 22:32 UTC

    When I got your post, I was reading (again) perlsub to check that it's the same to pass an array by reference than by value to save memory, because of aliasing magic built in @_.

    Fortunately, shifting or directly assigning values into my variables, breaks that internal linking, so modifying them won't alter the source of the parameters as in foreach, but it exists the possibility power to do that by touching @_ directly.

    Unfortunately, assigning @_ to a local variable just to write clear code, all the parameters array will be duplicated.

    A test on this topic...

Re: I should've known better!
by Zen (Deacon) on Sep 14, 2009 at 14:04 UTC

    Perl and Perl Jr. on the links:

    for @text <-> $line
    24 keystrokes

    foreach $line(@text)
    24 keystrokes

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://794638]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others rifling through the Monastery: (5)
As of 2024-04-24 09:59 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found