【问题标题】:In Erlang, is there a way to pattern match against an enumerated set of atoms?在 Erlang 中,有没有办法对一组枚举的原子进行模式匹配?
【发布时间】:2013-07-20 04:49:13
【问题描述】:

我目前正在学习 Erlang,它的模式匹配是我最近看到的最酷的东西之一。我在练习中想出的一个小玩具功能如下:

b_and(true, true) ->
  true;
b_and(true, false) ->
  false;
b_and(false, true) ->
  false;
b_and(false, false) ->
  false;
b_and(_, _) ->
  {error, invalid_object}.

不过,我想知道,是否有语法可以告诉模式中的变量只接受一组枚举原子?那样的话,我可以把它缩短成这样:

b_and(true, true) ->
  true;
% We've already satisfied the only true case
b_and(ENUM(true, false), ENUM(true, false)) ->
  false;
b_and(_, _) ->
  {error, invalid_object}.

我查看了有关模式匹配的文档,但找不到类似的内容。

【问题讨论】:

    标签: erlang pattern-matching


    【解决方案1】:

    目前没有直接的方法将原子列表指定为模式。

    在你的情况下,你可以使用警卫,但它几乎不短

    b_and(true, true) -> true;
    b_and(A, B) when A =:= true or A =:= false,
                     B =:= true or B =:= false ->
        false.
    

    顺便说一句,当使用其他任何东西调用函数会出错时,通常会关闭错误子句。

    你可以使用这个解析转换https://github.com/mad-cocktail/gin,它会给你一个 in() 形式的守卫。问题是它是否值得,只是对于这么少且不经常使用的具有解析转换的功能似乎有点重量级。

    【讨论】:

    • 非常感谢。这是您所指的解析转换吗? github.com/mad-cocktail/gin
    • 没错,更新我的答案
    • 根据@Kaos 的建议:您绝对不应该在 b_and/2 中有错误子句!如果使用非布尔参数调用它应该会产生错误。通常类型错误会/应该产生异常,大多数库都遵循这个规则。
    【解决方案2】:

    在这种特殊情况下,您可以使用is_boolean 函数,它为原子truefalse 返回true,对于其他所有原子返回false

    b_and(true, true) ->
      true;
    b_and(A, B) when is_boolean(A), is_boolean(B) ->
      false;
    b_and(_, _) ->
      {error, invalid_object}.
    

    【讨论】:

      【解决方案3】:

      我只想强调@PeerStritzinger 关于错误条款的评论。您绝对应该b_and/2 中有错误子句!如果使用非布尔参数调用它应该会产生错误。通常类型错误确实/应该产生异常,大多数库都遵循此规则。

      【讨论】:

      • 罗伯特,这会更适合作为对 Peer 答案的评论,因为它本身并不是一个答案。作为评论,我会投票赞成 :)
      【解决方案4】:

      只是想就如何解决此类问题给出不同的答案:

      b_and(true, B) -> bool(B);
      b_and(false, B) -> bool(B, false).
      
      bool(B) -> bool(B, B).
      bool(true, Res) -> Res;
      bool(false, Res) -> Res;
      bool(_, _) -> {error, invalid_object}.
      

      但话又说回来,你真的不应该在这里屏蔽无效参数,除非你希望被错误的参数调用并且想要返回错误消息而不是异常。

      【讨论】:

      • 嗨,为什么不简单: b_and(true, B) -> bool(B) ; b_and(假,_)->假。布尔(真)->真;布尔(假)->假。
      • 这可能是我们更喜欢的方式,但是你不会得到{error, invalid_object}b_and(false, foo)(正如我试图在我的回答的结束语中暗示的那样)。
      【解决方案5】:

      你可以这样写,应该没问题。

      b_and(true,true) -> true ;
      b_and(A,B) when is_boolean(A),is_boolean(B) -> false.
      

      正如 Peer Stritzinger 所说,如果使用错误的参数调用,让它崩溃并确保使用布尔值调用它。

      【讨论】:

        猜你喜欢
        • 2011-01-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-05
        • 2018-01-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多