【问题标题】:How can you write a conditional based on the definedness of multiple variables?如何根据多个变量的定义编写条件?
【发布时间】:2020-10-08 11:35:34
【问题描述】:

我时不时地发现自己需要编写带有两个或三个分支的条件:至少一个用于定义所有两个或多个变量时,一个用于定义任何或没有定义的变量。有时最后一个分支需要是两个独立的分支。有什么短小精悍的写法?

【问题讨论】:

    标签: null conditional-statements undefined raku


    【解决方案1】:

    withwithoutorwith 是与 ifunlesselsif 类似的条件句,除了它们检查参数的定义性而不是真实性。与这些结合使用时,连接会成为线程,因此可以像这样编写这样的条件:

    my Str $foo = '' if 2.rand.floor;
    my Str $bar = '' if 2.rand.floor;
    with $foo & $bar {
        say 'yes';
    } orwith $foo | $bar {
        say 'maybe';
    } else {
        say 'no';
    }
    

    或者对于任意数量的变量:

    my Str @strings = do 2.rand.floor ?? '' !! Nil for ^3;
    with all @strings {
        say 'yes';
    } orwith any @strings {
        say 'maybe';
    } else {
        say 'no';
    }
    

    【讨论】:

    • 嗨@kaiepi - 你能解释一下我的 Str:_ ... 语句中的 :_ 是什么吗??
    • hi @kaiepi - 我担心 perl 作为线路噪音的声誉会在 perl6 中继续存在 - 所以我建议使用默认的“Str”,即 (i) 噪音较小的东西,并且(ii) 有人考虑过并定义过,除非我有误解并且 ':_' 中有一些价值
    • 在我自己的代码中,我更喜欢明确地使用类型的笑脸,但我可以理解为什么人们不喜欢:_。我会编辑它。
    【解决方案2】:

    with 等都很棒,我可能会写一个链接的 with 语句,特别是如果特定变量组合的匹配是临时的,或者我认为考虑到代码的预期演变可能会变得如此。

    但考虑到你的字面问题,以及你在回答中的场景,我更有可能选择given/when

    my ($foo, $bar, $baz) = (Mu, 42).pick xx Inf;
    
    given $foo, $bar, $baz {
      when .all.defined { say 'yes'   }
      when .any.defined { say 'maybe' }
      default           { say 'no'    }
    }
    

    【讨论】:

    • 这里使用when / default 有什么意义,如果你真的是说if / elsif / else
    • @ElizabethMattijsen ➊ 我更喜欢它的阅读方式。一个关键字而不是三个(default 是可选的外部异常处理程序)。 ➋ 没有$_ ~~when 很聪明。直到它出现才重要,但when 确实如此,它确实如此。 ➌ when 支持 proceed / succeed(语句修饰符 when 也是)。同样,这无关紧要,直到它发生,但if 没有,句号。 ➍ 每次我重构一个 set topic / if / elsif / else 链以适应 ➋ 或 ➌ 我都想到了 ➊ 和著名的 yagni 不太知名的恼人的同卵双胞胎(你 是会需要它)。 ➎ 如果速度很重要,我会使用if...
    【解决方案3】:

    您可以创建一个组合值并将签名用作when 条件。

    :(…) 是签名文字的语法。)

    given ($foo,$bar,$baz) {
       when :( Any:D, Any:D, Any:D ) { 'all defined' }
       when :( Any:D, Any:D, Any:U ) { '$baz undefined' }
       when :( Any:D, Any:_, Any:D ) { '$bar not checked' }
    
       default { … }
    }
    

    您可以创建词法常量以使其更短。

    my constant D = Any:D; # defined
    my constant U = Any:U; # undefined
    my constant _ = Any:_; # either
    
    given ($foo,$bar,$baz) {
       when :(D,D,D) { 'all defined' }
       when :(D,D,U) { '$baz undefined' }
       when :(D,_,D) { '$bar not checked' }
    
       default { … }
    }
    

    或者如果你想让它更直观:

    my constant term:<▣> = Any:D; # defined
    my constant term:<□> = Any:U; # undefined
    my constant term:<▨> = Any:_; # either
    
    given ($foo,$bar,$baz) {
       when :(▣,▣,▣) { 'all defined' }
       when :(▣,▣,□) { '$baz undefined' }
       when :(▣,▨,▣) { '$bar not checked' }
    
       default { … }
    }
    

    您可以创建一个子例程,让 Signature 改为使用。

    ## something like this should work
    ## but something is weird with the returns constraint
    #sub prefix:<d> ( $_ ) {
    #  my constant %lookup = (
    #    '▣' => Parameter.new( type => Any:D ),
    #    '□' => Parameter.new( type => Any:U ),
    #    '▨' => Parameter.new( type => Any:_ ),
    #  );
    #  Signature.new: params => %lookup{.comb}
    #}
    
    sub prefix:<d> ( $_ ) {
      my constant %lookup = (
        '▣' => 'Any:D',
        '□' => 'Any:U',
        '▨' => 'Any:_',
      );
      use MONKEY-SEE-NO-EVAL;
      EVAL ":(%lookup{.comb}.join(","))"
    }
    
    given ($foo,$bar,$baz) {
       when d'▣▣▣' { 'all defined' }
       when d'▣▣□' { '$baz undefined' }
       when d'▣▨▣' { '$bar not checked' }
    
       default { … }
    }
    

    【讨论】:

      猜你喜欢
      • 2021-12-16
      • 1970-01-01
      • 1970-01-01
      • 2023-02-25
      • 2012-09-01
      • 2014-05-17
      • 1970-01-01
      • 2019-09-27
      • 1970-01-01
      相关资源
      最近更新 更多