erwan has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

I just spent two days finding a bug in a complex program, which turned out to be related to $_... again (see http://www.perlmonks.org/?node_id=1154900). Here is a short version of the problem I had:

#!/usr/bin/perl use strict; use warnings; use bug::myitem; sub generate { my $list = shift; my @data; my $i=0; foreach my $f (@$list) { my $item = bug::myitem->new($i++, $f); push(@data, [$item, $i]); } return \@data; } my $data; if (scalar(@ARGV)>0) { $data = generate(\@ARGV); } else { die "syntax: <file1> <file2> ..." } print "Before:\n"; foreach my $item (@$data) { print "item->[0]=".$item->[0]." ; item->[1]=".$item->[1]."\n"; } my $dataStuff = map { $_->[0]->getContent() } @$data; print "After:\n"; foreach my $item (@$data) { print "item->[0]=".$item->[0]." ; item->[1]=".$item->[1]."\n"; }

and the class is this:

package bug::myitem; use strict; use warnings; sub new { my ($class, $id, $file) = @_; my $self; $self->{id} = $id; $self->{file} = $file; bless($self, $class); return $self; } sub getContent() { my $self = shift; my $fh; my $res; open($fh, "<",$self->{file}) or die "cannot open '".$self->{file}. +"'"; while (<$fh>) { chomp; $res .= $_."***"; } return $res; } 1;

I see now that I need to set $_ as local. I find it quite counter-intuitive to have to explicitly make local the default variable. My conclusion would be that I should always make it local whenever I use it, unless I intend to use it globally... and actually I can't think of any case where using it globally would be good programming practice.

What do you expert think? Thank you for your insight!

Replies are listed 'Best First'.
Re: Good practice with $_ scope?
by davies (Monsignor) on Jun 12, 2016 at 14:53 UTC

    If you don't have standards telling you when to do these things (if, like me, you are coding for your own fun & education or if you are a one man shop), then you should do what fits your brain. If you find it clearer to localise $_ every time, go ahead. My attitude is that, if there is the slightest possibility of confusion, I assign to a named variable rather than use $_. So part of your code might, in my idiom, become:

    use Modern::Perl; my $res; while ($res = <DATA>) { chomp $res; say $res . "***"; } __DATA__ 1234 qwer asdf zxcv

    But if you are working alongside anyone else, ask them what they do or, if they are unfamiliar with the construct, what they find clearest. They may have to maintain your code or you theirs. In either case, it would be better if you had a common style and understood each other's idioms.

    Regards,

    John Davies

Re: Good practice with $_ scope?
by BrowserUk (Patriarch) on Jun 12, 2016 at 15:18 UTC

    My "best practice" is: don't use globals in packages without localisation.

    Globals belong to the main program.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
    In the absence of evidence, opinion is indistinguishable from prejudice. Not understood.
Re: Good practice with $_ scope?
by Anonymous Monk on Jun 12, 2016 at 14:27 UTC
    From I/O Operators:
    If and only if the input symbol is the only thing inside the conditional of a while statement (even if disguised as a for(;;) loop), the value is automatically assigned to the global variable $_, destroying whatever was there previously. (This may seem like an odd thing to you, but you'll use the construct in almost every Perl script you write.) The $_ variable is not implicitly localized. You'll have to put a local $_; before the loop if you want that to happen.