【问题标题】:How to define a wildcard pattern using cerl:c_clause如何使用 cerl:c_clause 定义通配符模式
【发布时间】:2013-07-17 13:07:27
【问题描述】:

我正在尝试将一些个人语言编译为 erlang。我想创建一个对子句进行模式匹配的函数。

这是我的数据:

Data =
    [ {a, <a_body> }
    , {b, <b_body> }
    , {c, <c_body> }
    ].

这就是我想要的:

foo(a) -> <a_body>;
foo(b) -> <b_body>;
foo(c) -> <c_body>;
foo(_) -> undefined. %% <- this

我现在这样做:

MkCaseClause =
    fun({Pattern,Body}) ->
        cerl:c_clause([cerl:c_atom(Pattern)], deep_literal(Body))
    end,
WildCardClause = cerl:c_clause([ ??? ], cerl:c_atom(undefined)),
CaseClauses = [MkCaseClause(S) || S <- Data] ++ [WildCardClause],

所以请帮我定义WildCardClause。我看到如果我用既不 a 也不 b 也不 c 调用我的编译函数,它会导致 ** exception error: no true branch found when evaluating an if expression in function ...。

当我打印我的 Core Erlang 代码时,我得到了这个:

'myfuncname'/1 =
    fun (Key) ->
        case Key of
          <'a'> when 'true' -> ...
          <'b'> when 'true' -> ...
          <'c'> when 'true' -> ...
        end

好吧,当内核编译时,case 被翻译成if。所以我需要在if 表达式中指定true 子句以获得纯通配符。我不知道该怎么做,因为在 if 表达式和 case 中匹配 true 是不同的语义。在某种情况下,true 不是通配符。

如果我想匹配带有通配符的表达式,比如{sometag,_,_,Thing} -&gt; {ok, Thing}。

谢谢

【问题讨论】:

    标签: compilation programming-languages erlang


    【解决方案1】:

    我已经找到了一种方法来做到这一点

    ...
    WildCardVar = cerl:c_var('_Any'),
    WildCardClause = cerl:c_clause([WildCardVar], cerl:c_atom(undefined)),
    ...
    

    它也应该适用于内部通配符,但必须小心为每个 _ 通配符赋予不同的变量名称,因为只有多个 _ 不匹配,变量匹配。

    f(X,_, _ ) %% matches f(a,b,c)
    f(X,_X,_X) %% doesn't
    

    【讨论】:

    • 接受我自己的答案,因为经过进一步研究,erlang 就是这样做的。因为这是唯一的答案:)
    猜你喜欢
    • 2013-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-24
    • 2018-11-25
    • 2012-10-03
    相关资源
    最近更新 更多