Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where does $_ come from in this Perl foreach loop?

Tags:

perl

I found this in Mail::IMAPClient. Where does the $_ in $SEARCH_KEYS{ uc($_) } come from?

sub _quote_search {
    my ( $self, @args ) = @_;
    my @ret;
    foreach my $v (@args) {
        if ( ref($v) eq "SCALAR" ) {
            push( @ret, $$v );
        }
        elsif ( exists $SEARCH_KEYS{ uc($_) } ) {
            push( @ret, $v );
        }
        elsif ( @args == 1 ) {
            push( @ret, $v );    # <3.17 compat: caller responsible for quoting
        }
        else {
            push( @ret, $self->Quote($v) );
        }
    }
    return @ret;
}
like image 796
sid_com Avatar asked Apr 29 '10 09:04

sid_com


People also ask

What is $_ in Perl?

The most commonly used special variable is $_, which contains the default input and pattern-searching string. For example, in the following lines − #!/usr/bin/perl foreach ('hickory','dickory','doc') { print $_; print "\n"; }

What is foreach loop in Perl?

A foreach loop runs a block of code for each element of a list. No big whoop, “perl foreach” continues to be one of the most popular on Google searches for the language.

Which can be correct syntax of foreach in Perl?

A foreach loop is used to iterate over a list and the variable holds the value of the elements of the list one at a time. It is majorly used when we have a set of data in a list and we want to iterate over the elements of the list instead of iterating over its range.

How do I end a foreach loop in Perl?

In many programming languages you use the break operator to break out of a loop like this, but in Perl you use the last operator to break out of a loop, like this: last; While using the Perl last operator instead of the usual break operator seems a little unusual, it can make for some readable code, as we'll see next.


2 Answers

That looks to me like a typo where the author converted an anonymous for loop foreach (@args) to one with an explicit iterator variable foreach my $v (@args) and forgot to convert all the incidences of $_ to $v.

You should probably file a bug against the distribution on CPAN.

like image 133
Ether Avatar answered Oct 15 '22 02:10

Ether


Even though this is probably a bug, lets consider how this code behaves.

The value of $_ will be determined by the current dynamic scope. What this means is that $_ will have whatever value (the dynamically scoped copy of) $_ has in the calling subroutine.

So for example if I have:

for (1 .. 5 ) {
    foo();
    bar();
}

sub foo {
     print "\$_ = $_\n";
}

sub bar {

    for ( 'a' .. 'c' ) {
        foo();
    }
}

You get output like:

$_ = 1
$_ = a
$_ = b
$_ = c
$_ = 2
$_ = a
$_ = b
$_ = c
...

It gets a little weirder in Perl 5.10 and up, where a lexical $_ exists.

for (1 .. 5 ) {
    foo();
    bar();
}

sub foo {
     print "\$_ = $_\n";
}

sub bar {
    my $_;
    for ( 'a' .. 'c' ) {
        foo();
    }
}

Run this and get:

$_ = 1
$_ = 1
$_ = 1
$_ = 1
$_ = 2
$_ = 2
$_ = 2
$_ = 2

As you can see, if this isn't a bug, it's probably a bad idea.

like image 22
daotoad Avatar answered Oct 15 '22 02:10

daotoad