Perl использует дополнительный вызов в качестве аргумента для другого неожиданного контекста - PullRequest
5 голосов
/ 31 июля 2010

Я использую дополнительный вызов в качестве аргумента для другого дополнительного. Пример кода:

test(isInString(), 'second parameter', 'third parameter');

sub test {
    my ($boolean, $second, $third) = @_;
    print "boolean: $boolean\n second: $second\n third: $third\n";
}

sub isInString {
    my $searchFor = 'a'; 
    my $searchIn = 'bcd';   

    return ($searchFor && $searchIn && ($searchIn =~ $searchFor));
}

В приведенном выше примере я ожидал бы, что оператор return в "isInString" будет иметь значение false ('' или undef или что-то еще, что может быть в perl), и это будет передано в "Test" как параметр # 1 итак, у тебя по существу будет

Test(undef, 'second parameter', 'third parameter');

Это не то, что происходит, хотя. isInString возвращает пустой массив, и, по сути, вы получаете

Test('second parameter', 'third parameter');

возвращение из isInString в отладчике perl дает:

возвращение контекста списка из main :: isInString: пустой массив

Я предполагаю, что это контекст Perl, я могу сначала назначить скалярную переменную, и она отлично работает:

my $bool = isInString();
Test($bool, 'second parameter', 'third parameter');

отладчик дает - возвращение скалярного контекста из main :: isInString: ''

РЕДАКТИРОВАТЬ Я удалил все парены с одинаковым результатом:

sub isInString {
        my $searchFor = 'a'; 
        my $searchIn = 'bcd';   

        return $searchFor && $searchIn && $searchIn =~ $searchFor;
    }

Отладчик по-прежнему выдает:

возвращение контекста списка из main :: isInString: пустой массив

Может кто-нибудь объяснить, почему он возвращает контекст списка / пустой массив в этом сценарии?

Ответы [ 3 ]

7 голосов
/ 31 июля 2010

Ваш return оценивается в контексте списка, потому что функция вызывается в контексте списка. Логические операторы (например, &&) делают , а не форсируют скалярный контекст.

Цитировать perlop на &&:

Скаляр или контекст списка распространяется вниз правый операнд, если это оценены.

Поскольку оператор сопоставления возвращает пустой список при неудаче в контексте списка, это то, что вы получаете. Если вы хотите форсировать скалярный контекст, используйте оператор scalar, либо в вашем операторе return, либо при вызове функции.

Кроме того, идея, заключающаяся в том, что скобки заставляют контекст списка (как предлагается в некоторых других ответах), является распространенным заблуждением. Они не Контекст списка является значением по умолчанию; все, что может быть списком, является списком. Вот почему нет оператора list, который соответствует scalar. Единственное место, где паренс "форсирует" контекст списка, это оператор повторения. 'a' x 3 означает 'aaa', но ('a') x 3 означает ('a', 'a', 'a'). Но это на самом деле не форсирует контекст списка, это просто особый случай для оператора x .

3 голосов
/ 31 июля 2010

Если вы хотите форсировать «логический контекст», вы можете использовать двойной отрицательный «оператор»: !!, например:

test( !!isInString(), 'second parameter', 'third parameter' );

Вызывая его в списке параметров, вывынудили его в "список контекста".Вы можете заставить его вернуться с чем-то вроде этого.Один удар (!) оценивает его в логическом контексте и делает его равным 1 или ''.Но поскольку вы тестируете не дополнение, а само значение, добавление другого удара возвращает вам желаемое значение.

Однако, поскольку из тела функции довольно ясно, что вы возвращаете логическое значение, и вы вызываете его в контексте списка (список параметров является контекстом списка), вы можете захотеть принудительно установить определенное значение.Например:

return ($searchFor && $searchIn && $searchIn =~ $searchFor) || 0;

Любой undef приведет к ложному значению, и он перейдет к или и вернет 0, который контекст списка не будет игнорировать, так как он может undef.

0 голосов
/ 01 августа 2010

Не относится к вашему вопросу, но index() является более подходящим для вашей isInString() функции.

index( $searchIn, $searchFor );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...