如何使用cerl定义通配符模式:c_clause

时间:2013-07-18 14:11:15

标签: compilation programming-languages erlang

我正在尝试为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。所以我需要在true表达式中指定if子句以获得纯通配符。我不知道该怎么做,因为在true表达式和if表达式中匹配case是不同的语义。在一种情况下,true不是通配符。

如果我想将表达式与{sometag,_,_,Thing} -> {ok, Thing}内的通配符匹配,那该怎么办。

谢谢

1 个答案:

答案 0 :(得分:0)

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

...
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