Hacker News new | past | comments | ask | show | jobs | submit login

This is why wise Perl programmers turn on use strict, and then declare variables with my. Now attempting to dynamically scope stuff is a compilation error. (Except for some built in variables, like $_. Which you don't use in real programs.)

This has been standard advice since the last millennium. But you can't change it without breaking backwards compatibility.

That said, I do have several good uses for local. But not normal ones. My favorite is to use local to dynamically scope entries in a hash. I wind up using this every year or two to put in an automatic check to catch infinite recursion.




I like local for two big uses: One, in unit testing, it's a cheap way to completely mock out a function within some scope. I know there's various test methods for that, but frankly local'ing a glob is so easy both to use and to make do exactly what I need that it's often still easier than even invoking the library.

Second, I love it for security-related stuff where I really don't want something to escape a scope. I have a value that represents the current user I am processing a request for, which is used for security checks, and by local'ing the variable in the context of the handler, I can be very confident that it absolutely, positively will not escape into the next request.

It also turns out to mean that if you're in a code base that has some unfortunate "global" variables, that local lets you turn them into much less "global" variables, as you can local them with confidence about how it won't escape out of scope. Of course, the better solution is to not do that, or to fix it, but we don't live in a perfect world....


>variables, like $_. Which you don't use in real programs

Oh really? What's wrong with $_ and since when it is?


The problem is that $_ is global and always in package main.

A specific problem that fixed this in my memory was a bug in my co-worker's code which boiled down to his looping over an array with $_, then calling a function in his loop that was in a CPAN library that assigned to $_. The result was that he wiped out his whole array.

Whenever you are calling out to code that someone else wrote, you don't know if issues like that could exist, and therefore it isn't safe to use $_. Conversely if you're writing code that someone else will call, be a good citizen and don't assign to $_ either implicitly or explicitly.


It's also lexicalized in every loop, so writing to it doesn't affect anything else. The only time I can think of you would have to worry about this is if some function modified $_ without any loop, and I would consider that a bug (similar to any function that set a static class variable indiscriminately).

For example, the following code performs as expected, and prints "123"

    use 5.016;
    use warnings;
    my @a = qw(1 2 3);
    for (@a) {
        my @b = qw(4 5 6);
        for (@b) {
            $_ = 1;
        }
        print;
    }
This code works (prints "123") fine as well:

    use 5.016;
    use warnings;
    sub test {
        my @b = qw(4 5 6);
        for (@b) {
            $_ = 1;
        }
    }
    my @a = qw(1 2 3);
    for (@a) {
        test;
        print;
    }
The following causes a problem (prints "111"). Don't do this, it's stupid.

    use 5.016;
    use warnings;
    sub test {
        $_ = 1;
    }
    my @a = qw(1 2 3);
    for (@a) {
        test;
        print;
    }
The moral? Buggy libraries are buggy, don't use them, or submit a fix.


It is not lexicalized, it is localized.

And yes, I both fixed my coworker's code to not use $_, and submitted a patch to the CPAN library with the bug. But the experience taught me to be cautious about $_.


Sorry, that's correct. I have lexical on the brain.

I just think saying not to use $_ in real programs is a bit extreme. Truthfully, I don't use it in for loops at all, but my code invariably uses a lot of maps and greps. To throw away the expressiveness of map and grep because there may be a problem in some third party library I use at some point is too high a price for me. Especially because by the nature of how I use map and grep I think I'm less likely to run into problem code in those cases, and if I do I think it will be fairly obvious.


It's kind of obtuse. If you have to type out "$_", you might as well declare it and give it a good name.

I personally have no issues doing:

    foreach @array {
      chomp;
      print;
    }
But as soon as I have to type "$_" I make a real variable.


$_ is pronounced "it" and should only be used in small blocks of code. This is in much the same way that in a paragraph of text "it" should only be used for transitory sentences on the same topic as the previous one.


What's wrong to type $_ if you want to print "`$_'\n" in your example? Etc. I don't see any problem with that as $_ is clearly states that's a loop counter. And let's don't even talk about map/grep/sort and schwartzian transform.


I don't think he sees that as a Problem. Only he thinks using it explicitly is not to his taste. I have a similar attitude: make it explicitly a new var if it is going to appear in the code.

Your example is perfectly OK.

TIMTOWTDI, really.




Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: