【问题标题】:What kind of syntactic sugar is available in Perl to reduce code for l/rvalue operators vs. if statements?Perl 中有哪些语法糖可以减少 l/rvalue 运算符与 if 语句的代码?
【发布时间】:2011-12-09 10:26:45
【问题描述】:

那里有很多,因为 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})

有人在“秘密操作员”上也有一个really interesting article,如下所示:

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?

还有什么值得补充的吗?还有哪些其他条件集变量可用于减少代码?还缺少什么?

【问题讨论】:

  • $c &amp;&amp; $r = $s 需要多加一点糖(你不得不说($r=$s)
  • @mob,恐怕这对 OP 来说是相当苦涩的味道 :-)
  • $r = !$s ? $s : $t$r = $s &amp;&amp; $t 是一样的
  • min($r, $s) 不能短路。必须检查每个元素才能找到最小的元素。
  • @ikegami:是的,但更多的是操作。例如,标准最小值将执行以下操作:读取 $r,读取 $s,放入 $list,循环并找到最小值,存储到 $r。当我需要做的只是:比较 $r 和 $s,STOP 或将 $s 存储在 $r 中。那是短路。

标签: perl logical-operators syntactic-sugar rvalue


【解决方案1】:

Perl 中最需要的功能之一是switch statement。这最终出现在 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 &amp;&amp;= $s 更酷,而且它为你赢得了更多的极客积分,而且打字更少,但它的执行速度并没有更快。花在代码上的最大时间是在维护它,所以我宁愿跳过花哨的东西并追求可读性。

顺便说一句,当我想到 语法糖 时,我想到了添加到语言中以提高可读性的东西。一个很好的例子是-&gt; 运算符:

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

对比

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

当然,如果您将数据作为对列表的引用存储到对列表的散列,则最好使用面向对象的编码。

【讨论】:

  • 要回答您关于使用功能的问题,只需“使用 common::sense;”有史以来最好的模块!就可读性而言,它的可读性取决于可能理解或可能不理解它的人。例如,有人可能不知道$a || die 的真正作用,但它无处不在。因此,人们倾向于回避 ~~ 智能匹配运算符,但所需要做的就是查找参考。值得努力做一些像@q ~~ $val 这样简单的事情,而不是为第一个、for 循环或其他任何事情而烦恼。
  • given/when 有这样的名字是因为它们是从 Perl 6 移植过来的。在 Perl 6 中它们被重命名是因为它们比通常的 switch/case 做得更多
  • 我不知道你,但我喜欢想到$$employee_ref[0]{phone}[0] :)
【解决方案2】:

$r = $r &lt; $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;

【讨论】:

    【解决方案3】:

    使用低优先级 andor 关键字可以更清楚地写出您问题中的这些结构:

    $c and return $r;    # return $r if ($c);
    $c or return $r;     # return $r unless ($c);
    $c and $r = $s;      # $r = $s if ($c);
    

    andor 的好处在于,与语句修饰符控制字不同,andor 可以链接成复合表达式。

    语法糖的另一个有用工具是使用for/foreach 循环作为单个值的主题化器。考虑以下几点:

    $var = $new_value if defined $new_value;
    

    defined and $var = $_ for $new_value;
    

    或类似的东西:

    $foo = "[$foo]";
    $bar = "[$bar]";
    
    $_ = "[$_]" for $foo, $bar;
    

    map 函数也可以通过这种方式使用,并且有一个可以使用的返回值。

    【讨论】:

    • 哦,我忘了 and/or 词了。是的,我经常使用 map 来定义 my ($id, $name) = map { $DEV-&gt;{$d}{$_} } qw(hostid hostname);
    • 别忘了切片:my ($id, $name) = @{$$DEV{$d}}{qw(hostid hostname)};
    【解决方案4】:

    还有左边的三元运算符:

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

    相当于:

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

    【讨论】:

      【解决方案5】:

      还有:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-02-15
        • 1970-01-01
        • 2018-02-11
        • 2016-02-28
        • 2019-06-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多