in reply to Re: Action at a great distance
in thread Action at a great distance

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...

It was extra annoying because the error doesn't pop up until the next use of the callback, at which time you just see a strangely mangled @cb array. When I tracked it back, I was rather surprised when my debugging printouts showed that the callback was set to each line of the file I was reading, in turn...

I knew about the scope of $_, and I certainly know about the aliasing of subroutine parameters, but somehow it nevers seemed to be a problem in practice. I could just happily ignore it. Until now.

I believe the root cause is that $_ came well before perl used lexical scopes, and changing it to be lexical would have broken far too many scripts. Maybe we should start working on a new major version of Perl that jettisons some of these legacy features... oh, wait...

Replies are listed 'Best First'.
Re: Re: Re: Action at a great distance
by perrin (Chancellor) on Mar 17, 2004 at 22:25 UTC
    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.
Re: Re: Re: Action at a great distance
by stvn (Monsignor) on Mar 18, 2004 at 01:32 UTC

    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