in reply to Action at a great distance

One of those callbacks could modify $_.

Replies are listed 'Best First'.
Re: Re: Action at a great distance
by sfink (Deacon) on Mar 17, 2004 at 22:10 UTC
    Yes, exactly what I was thinking of, and what I ran into.

    Here's a complete chunk of code that illustrates the problematic behavior (I'll leave it exposed as an added hint):

    my @cb = (\&callback); $_->() foreach (@cb); sub callback { open(my $fh, "/tmp/somefile") or die; while(<$fh>) { print "orange!\n" if /red/; } }
    The observed behavior was an 'undefined subroutine' error -- and yet, if you cut & paste the above code, it will run fine. (So the above is buggy, but simply running it will not reveal the error.)

    Spoilers ahead...

      In this case, I'd say it's bad style to use $_ instead of a named variable for that loop anyway. You could localize $_, but I'd consider that an uglier solution.

      This is exactly why I try not to use $_ unless in map or grep (but it's not like I have a choice there anyway). This foreach shortcut is ripe with problems just like this. I have always felt that it is much better to take the few seconds of time to type what you mean explicity rather than have to spend alot more time hunting around for an insidious bug like this. That is the right kind of laziness IMO.

      I hate to say it, but its idioms like this that give perl such a bad rap. Sure you can bang out a script in 30 seconds that does the work of 6 Java programmers, but at what cost? There is nothing worse than having to maintain a 12-headed monster that was born as that 30 second script. Do future programmers a favor, hell do the perl community as a whole a favor, and take the time to type the few extra characters (Note to OP: this is not directed at you specifically but at the perl community-at-large).

      Now go ahead do what you will, I care not for the XP ;-P

      -stvn
Re: Action at a great distance
by jonadab (Parson) on Mar 17, 2004 at 20:45 UTC

    ;$;=sub{$/};@;=map{my($a,$b)=($_,$;);$;=sub{$a.$b->()}} split//,".rekcah lreP rehtona tsuJ";$\=$;[-1]->();print

      Are we still avoiding spoilers? I'll just play it safe.