Откуда берется $ _ в этом цикле Perl foreach?

#perl

#perl

Вопрос:

Я нашел это в Mail::IMAPClient. Откуда берется $_ in $SEARCH_KEYS{ uc($_) } ?

 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;
}
  

Комментарии:

1. Похоже, что это должно быть $ v. Иногда то, что вы видите, является ошибками. 🙂

2. Поскольку 8 из 10 ошибок, которые я нахожу в конце, не являются ошибками, я немного осторожен.

3. Все еще остаются 2/10, которые являются 🙂

Ответ №1:

На мой взгляд, это похоже на опечатку, когда автор преобразовал анонимный цикл for foreach (@args) в цикл с явной переменной итератора foreach my $v (@args) и забыл преобразовать все случаи $_ в $v .

Вероятно, вам следует сообщить об ошибке в дистрибутиве на CPAN.

Ответ №2:

Даже если это, вероятно, ошибка, давайте рассмотрим, как ведет себя этот код.

Значение $_ будет определяться текущей динамической областью. Это означает, что $_ будет иметь любое значение (динамически расширяемая копия), $_ имеющееся в вызывающей подпрограмме.

Так, например, если у меня есть:

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

sub foo {
     print "$_ = $_n";
}

sub bar {

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

Вы получаете вывод, подобный:

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

Это становится немного более странным в Perl 5.10 и выше, где существует лексическое $_ значение.

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

sub foo {
     print "$_ = $_n";
}

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

Запустите это и получите:

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

Как вы можете видеть, если это не ошибка, то, вероятно, это плохая идея.

Комментарии:

1. Сохраняет ли лексическое значение $_ значение? Это не работает: $ _ = 10; { my $_; say; }

2. Хорошо, может быть, это foo, который сохраняет значение.

3. @Eric, не совсем, но 99% моей работы должно быть совместимо с Perl 5.8. Это важно учитывать при просмотре опубликованного кода.

4. @sid, $_ это глобальная переменная, которая получает новую динамическую область видимости (как вы получаете через local ) в каждом цикле for. Таким образом, foo() просто выводится любое значение, находящееся в том, на что $_ указывает во время его вызова. bar локализуется $_ , и поэтому теперь оно указывает на другое значение. Взгляните на то, как справиться с областью видимости. Здесь подробно рассказывается о том, как работает динамическое определение области видимости. perl.plover.com/FAQs /…