Perl логично и с несколькими тестами

Нормально ли так написать:

if(($x && $y && $z) eq "test"){

}

Если я заинтересован в ($x eq "test") && ($y eq "test") && ($z eq "test")?

3 ответа

Решение

Это не было бы нормально, потому что это даже не работает

$x && $y либо возвращает $x или же $y в зависимости от того, является ли значение $x это правда или нет.

Это означает, что ($x && $y) && $z либо возвращает $x, $y или же $z в зависимости от значений $x а также $y,

Это означает, что только один из $x, $y или же $z будет сравниваться с 'test',

Например, вы получите ложное срабатывание (возвращает true, когда должно возвращаться false), когда у вас есть $x='abc'; $y='def'; $z='test';,

Если вы хотите что-то короче, то вам придется использовать что-то вроде

use List::MoreUtils qw( all );

if ( all { $_ eq "test" } $x, $y, $z )

Нет.

Выражение $x && $y && $z эквивалентно выражению

$x ? $x : $y ? $y : $z

и будет оцениваться отдельно от выражения на другой стороне eq оператор.

Пишу if ($x eq 'test' && $y eq 'test' && $z eq 'test') ... как вы делаете, настолько кратко, как вы собираетесь получить.

В качестве уточнения ответа Икегами я подумал, что покажу код для all() Подпрограмма, как это довольно просто, и дает хорошую демонстрацию логики ответа на вопрос. А также, как это бывает, делает хорошую демонстрацию того, как работают прототипы.

sub all (&@) {
    my $f = shift;
    foreach ( @_ ) {
        return NO unless $f->();
    }
    return YES;
}

Прототипы & а также @ обратитесь к ссылке на код и список аргументов. YES а также NO константы для true и false определены следующим образом:

# Use pure scalar boolean return values for compatibility with XS
use constant YES => ! 0;
use constant NO  => ! 1;

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

С этим кодом и этими прототипами мы можем использовать all подпрограмма очень похожа map сначала с блоком кода:

all { $_ eq "foo" } "foo", "bar", "baz";

Если мы удалим прототипы (&@) мы должны передать ссылку на код как отдельную часть списка:

all sub { $_ eq "foo" }, "foo", "bar", "baz";

Обратите внимание на добавление sub ключевое слово и запятая после блока кода.

Другие вопросы по тегам