【问题标题】:How to write "a==b ? X : Y" in Erlang, in other words how to write a C-style ternary operator?如何在 Erlang 中编写 "a==b ? X : Y",换句话说,如何编写 C 风格的三元运算符?
【发布时间】:2011-05-23 04:51:40
【问题描述】:

有没有在 Erlang 中编写这样的代码的好方法?

A == B ? X : Y

下面是 ruby​​ 风格的代码。这也称为ternary operator

【问题讨论】:

  • 你确实知道你写的和a == b是一样的,对吧?这真的是你想要的,还是别的什么?
  • @Gabe 在 C 或具有类似 C 语法的语言中,当然。不过,这不是有效的 erlang :-)
  • erlang 中的所有if 语句已经是一个表达式......我不确定这个问题在问什么。你在寻找类似if cond -> true_expr; true -> false_expr; end 的东西吗?还有case,可能更可取,视情况而定。
  • ab 在 erlang 中是不等的原子。你可以把它写成false
  • 另见this question

标签: erlang conditional-operator


【解决方案1】:

我们使用这样的宏:

-define(IF(Cond,E1,E2), (case (Cond) of true -> (E1); false -> (E2) end)).

然后在你的代码中编写:

io:format("~s~n", [?IF(a==b, "equal", "not equal")]).

【讨论】:

    【解决方案2】:

    说明

    三元运算符_ ? _ : _ 存在于许多语言中的原因是它们有两个句法类:语句和表达式。由于 if-then-else 结构通常属于语句类,因此当您输入表达式时,没有办法让它工作。因此,您将 _ ? _ : _ 运算符添加到表达式类。

    正如另一篇文章所述,您可以使用a == b ? true : false 并只写a == b,但这并不能解释我们可能有a == b ? X : Y 用于任意表达式XY 的一般情况。另请注意,a == b 在 Erlang 中始终为 false,因此您可能会争辩说,真正要做的是将整个表达式替换为 false

    幸运的是,与大多数函数式语言一样,Erlang 只有一个句法类,即表达式。因此,您可以在函数的任何位置使用case a == b of X -> ...; Y -> ... end,包括其他表达式。换句话说,三元 _ ? _ : _ 运算符在 Erlang 中是多余的,因为 case 已经可以工作了。

    一个例子:

    假设我们要返回一个简单的 proplist,并且我们需要进行一些计算

      f() ->
        case a == b of
              true -> 
               [{a, 3},
                {b, <<"YE">>},
                {c, 7}];
              false ->
               [{a, 3},
                {b, <<"YE">>},
                {c, "HELLO!!!"}];
        end.
    

    但由于 case 构造是一个表达式,我们可以内联它:

      f() ->
        [{a, 3},
         {b, <<"YE">>},
         {c, case a == b of
              true -> 7;
              false -> "HELLO!!!"
             end}].
    

    把事情做完。

    为什么我不提倡使用 IF

    Erlang 中的if .. end 构造通常不是您想要的。在这种情况下,您想仔细检查一个值 a == b,它可以产生两个输出之一 truefalse。在这种情况下,case-表达式更直接。如果您必须检查多个不同的测试并选择第一个匹配项,则最好使用if,而我们这里只需要进行一个测试。

    【讨论】:

    • 只想提一下,在 Ruby 的情况下,特别是使用三级运算符主要是为了方便。比较 a = if false then "T" else "F" enda = false ? "T" : "F"。两种形式都有效。
    • “三元运算符 _ ? _ : _ 存在于许多语言中的原因是它们有两个句法类”虽然这是真的,但我在支持它的语言中使用它的真正原因是因为它比其他方法更简洁。的确,语句和表达式之间是有区别的,我理解两者的区别,但我选择使用_?_:_的原因始终是基于代码的清晰性。
    【解决方案3】:

    如果您要问如何将A == B ? X : Y 之类的东西写成if 表达式,那就是

    if
        A == B ->
            X;
        true ->    % "true" means "else" here
            Y
    end
    

    你也可以写成case表达式:

    case A == B of
        true ->
            X;
        _Else ->
            Y
    end
    

    case A == B of
        true ->
            X;
        false ->
            Y
    end
    

    【讨论】:

      【解决方案4】:

      由于a == b ? true : false 映射到a == b,您也可以在Erlang 中使用a == b

      【讨论】:

      • 为了清楚起见:要成为有效的 erlang,您需要将“a”和“b”设为大写,即变量。否则它将比较原子'a'和b'。该匹配将始终失败,因此表达式将始终返回 false。
      • 谢谢@sfinnie。我真的不知道 erlang,所以没有抓住案例问题。
      【解决方案5】:

      你可以这样使用'if'

      foo(A,B) ->
          [1,
           2,
           (if A == B -> 3; true -> 4 end), % A == B ? 3 : 4
           5,
           6].
      

      special ?: 形式似乎不是必需的。您当然可以使用 true/false 作为返回值,但我认为您的意思是更通用的形式,因为那样没有用(A == B 做同样的工作)。

      【讨论】:

        【解决方案6】:

        @Gabe's answer 是最简洁的,并且(据我所知)是惯用的。 C 表达式 ((A==B) ? X : Y) 直接映射到 Erlang 表达式

        case A == B of
            true -> X;
            false -> Y
        end
        

        但是,这个比 C 版本的代码要多得多。你可能应该把它包装成一个方便的函数——有人应该告诉我这是否已经存在于 Erlang 标准库中!

        iff(true, X, Y) -> X;
        iff(false, X, Y) -> Y.
        

        那么你的 C 表达式就变成了简单的iff(A == B, X, Y)但是,请注意! 就像 C 语言一样,Erlang 急切地评估函数参数。如果XY 有副作用或评估成本很高,那么iff 将不等同于内联case 表达式。

        【讨论】:

          猜你喜欢
          • 2014-10-01
          • 1970-01-01
          • 1970-01-01
          • 2020-12-02
          • 1970-01-01
          • 1970-01-01
          • 2018-06-27
          • 2021-07-18
          • 2021-05-17
          相关资源
          最近更新 更多