Какой синтаксический сахар доступен в 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 the opposite of //?
$r and return $r          # can that be done without repeating $r?

Есть ли что-нибудь еще, что стоит добавить? Какие еще условные переменные набора доступны для сокращения кода? Что еще не хватает?

Ответы

Ответ 1

Эти структуры из вашего вопроса могут быть написаны немного более четко с использованием ключевых слов с низким приоритетом 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 также может использоваться таким образом и имеет возвращаемое значение, которое вы можете использовать.

Ответ 2

Там также тернарный оператор левой стороны:

$cond ? $var1 : $var2 = "the value";

эквивалентно:

if ($cond) {
    $var1 = "the value";
} else {
    $var2 = "the value";
}

Ответ 3

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

Ответ 4

Одной из самых больших названных функций в 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);
    }
}

Почему o 'почему они отправились с 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, и он зарабатывает, он зарабатывает вам больше очков geek и меньше набирает, он не выполняется быстрее. Самое большое количество времени, затрачиваемого на код, - на его поддержание, поэтому я предпочел бы пропускать причудливые вещи и идти на удобочитаемость.

Кстати, когда я думаю о синтаксическом сахаре, я думаю о добавленных к языку вещах для улучшения удобочитаемости. Отличным примером является оператор ->:

${${${$employee_ref}[0]}{phone}}[0];

против.

$employee_ref->[0]->{phone}->[0];

Конечно, если вы храните данные в качестве ссылки на список хеша для списка, вам, вероятно, лучше использовать объектно-ориентированное кодирование.

Ответ 5

Там также:

$hash{$key||'foo'} = 1;  # if($key) { $hash{$key} = 1 } else { $hash{'foo'} = 1 }