Какой синтаксический сахар доступен в Perl для сокращения кода операторов l/rvalue по сравнению с операторами if?
Там есть куча, так как Perl - довольно сладкий язык, но наиболее часто используемые операторы на любом языке - это сочетание операторов if и значений настроек. Я думаю, что я нашел много из них, но все еще есть несколько пробелов. В конечном счете, цель состоит в том, чтобы не писать имя переменной более одного раза:
Вот что у меня так далеко:
$r ||= $s; # $r = $s unless ($r);
$r //= $s; # $r = $s unless (defined $r);
$r &&= $s; # $r = $s if ($r);
$r = $c ? $s : $t; # if ($c) { $r = $s } else { $r = $t }
$c ? $r : $s = $t; # if ($c) { $r = $t } else { $s = $t }
$r = $s || $t; # if ($s) { $r = $s } else { $r = $t }
$r = $s && $t; # if ($s) { $r = $t } else { $r = $s = undef, 0, untrue, etc. }
$c and return $r; # return $r if ($c);
$c or return $r; # return $r unless ($c);
$c and $r = $s; # $r = $s if ($c);
@$r{qw(a b c d)} # ($r->{a}, $r->{b}, $r->{c}, $r->{d})
У кого-то также была действительно интересная статья о "секретном операторе", показанная здесь:
my @part = (
'http://example.net/app',
( 'admin' ) x!! $is_admin_link,
( $subsite ) x!! defined $subsite,
$mode,
( $id ) x!! defined $id,
( $submode ) x!! defined $submode,
);
Тем не менее, я обнаружил, что отсутствует в списке:
$r <= $s; # read as "$r = min($r, $s);" except with short-circuiting
$r = $s if (defined $s); # what's the opposite of //?
$r and return $r # can that be done without repeating $r?
Есть ли что-то еще, что стоит добавить? Какие еще переменные условного набора доступны для сокращения кода? Что еще не хватает?
5 ответов
Эти структуры из вашего вопроса могут быть написаны немного более четко, используя низкий приоритет and
а также or
ключевые слова:
$c and return $r; # return $r if ($c);
$c or return $r; # return $r unless ($c);
$c and $r = $s; # $r = $s if ($c);
Хорошая вещь о and
а также or
что в отличие от управляющих слов модификатора оператора, and
а также or
могут быть объединены в составные выражения.
Еще одним полезным инструментом для синтаксического сахара является использование for
/foreach
цикл как актуализатор для одного значения. Учтите следующее:
$var = $new_value if defined $new_value;
против
defined and $var = $_ for $new_value;
или такие вещи, как:
$foo = "[$foo]";
$bar = "[$bar]";
$_ = "[$_]" for $foo, $bar;
map
Функция также может быть использована таким образом, и имеет возвращаемое значение, которое вы можете использовать.
Также есть левый троичный оператор:
$cond ? $var1 : $var2 = "the value";
эквивалентно:
if ($cond) {
$var1 = "the value";
} else {
$var2 = "the value";
}
$r = $r < $s ? $r : $s;
:
$r = $s if $r > $s;
или же
use List::Util qw( min );
$r = min($r, $s);
или же:
sub min_inplace {
my $min_ref = \shift;
for (@_) { $$min_ref = $_ if $$min_ref > $_; }
}
min_inplace($r, $s);
$r = $s if (defined $s);
:
$r = $s // $r;
$r = $t; $r = $s if (defined $s);
:
$r = $s // $t;
$r = !$s ? $s : $t;
:
$r = $s && $t;
Одной из самых востребованных функций в Perl была инструкцияswitch. Это наконец появилось в Perl 5.10. Я просто использую пример из документации:
use feature qw(say switch); #My preference
#use feature ":5.10"; #This does both "say" and "switch"
[...]
given($foo) {
when (undef) {
say '$foo is undefined';
}
when ("foo") {
say '$foo is the string "foo"';
}
when ([1,3,5,7,9]) {
say '$foo is an odd digit';
continue; # Fall through
}
when ($_ < 100) {
say '$foo is numerically less than 100';
}
when (\&complicated_check) {
say 'a complicated check for $foo is true';
}
default {
die q(I don't know what to do with $foo);
}
}
Почему они пошли с given
/when
и не switch
/case
как вы находите в большинстве языков, для меня загадка. И почему, если утверждение given
/when
Вы указываете это в use features
как switch
?
Увы, люди, которые приняли эти решения, находятся на более высоком уровне, чем я, поэтому я не имею права даже подвергать сомнению эти светила.
Я избегаю более экзотических вещей и придерживаюсь самого простого для понимания синтаксиса. Представьте себе человека, который должен пройти через ваш код и найти ошибку в добавлении функции, которая будет проще понять для этого человека:
$r &&= $s;
или же
if ($r) {
$r = $s;
}
И, может быть, я мог бы понять, что я действительно имел в виду:
if (not defined $r) {
$r = $s;
}
И в этом случае я мог бы даже сказать:
$r = $s if not defined $r;
Хотя мне обычно не нравятся постфиксные заявления if, потому что люди склонны пропускать if
часть при просмотре кода.
Perl компилируется во время выполнения, и компилятор довольно эффективен. Так что, хотя это гораздо круче, чтобы написать $r &&= $s
и он зарабатывает, он зарабатывает вам больше очков гика и меньше набирает, он не выполняется быстрее. Наибольшее количество времени, затрачиваемое на код, занимает его обслуживание, поэтому я бы предпочел пропустить модные вещи и перейти к удобочитаемости.
Кстати, когда я думаю о синтаксическом сахаре, я думаю о вещах, добавленных в язык для улучшения читабельности. Отличным примером является ->
оператор:
${${${$employee_ref}[0]}{phone}}[0];
против
$employee_ref->[0]->{phone}->[0];
Конечно, если вы сохраняете данные как ссылку на список в хэш к списку, вам, вероятно, лучше использовать объектно-ориентированное кодирование.
Есть также:
$hash{$key||'foo'} = 1; # if($key) { $hash{$key} = 1 } else { $hash{'foo'} = 1 }