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
ключевое слово и запятая после блока кода.