in reply to Using $_ as a temp var, especially in functions

The problem then comes in is that $_ is global, and if your function modifies it, that could cause a very, very nasty bug

I would tend to turn that statement around and say that if your code relies on $_ at a higher level, and clobbering it at a lower level results in chaos, then you shouldn't be using $_ at the higher level. There you should be using a lexical.

It's for this reason that I consider File::Find to be slightly brain-damaged, for it admonishes you to not modify the $_ you are given otherwise all hell breaks loose. The burden of correctness should be on the module, not the client using it. At least for older versions of perl, c.f. v5.005_03

File::Find assumes that you don't alter the $_ variable. If you do then make sure you return it to its original value before exiting your function.

Here, for instance, if you want to pass information to a callback, you should be using a function they could call instead of relying on $_.


print@_{sort keys %_},$/if%_=split//,'= & *a?b:e\f/h^h!j+n,o@o;r$s-t%t#u'

Replies are listed 'Best First'.
Re: Re: Using $_ as a temp var, especially in functions
by IlyaM (Parson) on Oct 23, 2002 at 11:09 UTC

    I would tend to turn that statement around and say that if your code relies on $_ at a higher level, and clobbering it at a lower level results in chaos, then you shouldn't be using $_ at the higher level.

    It is not that easy. Clobering $_ at a lower level can easily break map, for/foreach and grep constructs at a higher level as shown at this topic: while(<>) { ... } considered harmful.

    In short: would you rewrite code like

    my @result = map some_sub($_), qw(a b c d);

    to

    my @result = map { my $x = $_; local $_; some_sub($x) } qw(a b c d);

    to satisfy your requirement?

    --
    Ilya Martynov, ilya@iponweb.net
    CTO IPonWEB (UK) Ltd
    Quality Perl Programming and Unix Support UK managed @ offshore prices - http://www.iponweb.net
    Personal website - http://martynov.org

      If I had the chance, I would rewrite some_sub to work on lists, which would allow me to say

      my @result = some_sub(qw(a b c d));

      But I will grant you that that is a somewhat facetious answer, as I understand your question to mean an arbitrarily complicated map code block and not something as simple.

      But then were the map code block arbitrarily complicated, I would no longer be using map, but instead I would be using for, which would make the code look like:

      my @result; for my $thing(qw(a b c d)) { # complex code block that munges $thing followed by push @result, $thing; }

      On the Principle of Least Surprise, by and large I tend to put unsurprising code in maps and greps. That rules out function calls and other invisible things that might play around with $_. for blocks do not suffer from these problems because you can name your own topicalizer (or whatever it's called) with the for my $topic construct. If you stick to this, you can't be bitten by the types of problems you describe.

      <update> if you have code running around secretly overloading the + operator, then clobbering $_ is likely the least of your problems. Just because you can write code that dicks around with $_, doesn't mean you should. We'll just have to agree to disagree. Your point is valid and I find no fault with it, I just see things differently.</update>


      print@_{sort keys %_},$/if%_=split//,'= & *a?b:e\f/h^h!j+n,o@o;r$s-t%t#u'
        That rules out function calls and other invisible things that might play around with $_.

        Unfortunately in Perl nearly everything can do invisible things that might play around with $_. You think something like $x + $y is safe? Wrong if $x is an object that overloads '+' operator. Or do you think that, say, hash access is safe? Again it may be not if hash is tied. Besides to my taste map and grep constructs often are much more ideomatic than corresponding for construct that I simply don't want to rule out function calls because my code will be less pretty.

        In my opinion there is no excuse for not localizing $_ in a low level code.

        --
        Ilya Martynov, ilya@iponweb.net
        CTO IPonWEB (UK) Ltd
        Quality Perl Programming and Unix Support UK managed @ offshore prices - http://www.iponweb.net
        Personal website - http://martynov.org