2

我最近开始研究 Erlang,遇到了一个我无法解释的奇怪异常。

我的源代码如下:

-module(balanced_brackets).                                                                                                              
-author("Irrelevant").
-compile(export_all).

is_balanced(String) -> is_balanced(String, 0, 0).

is_balanced([H | T], Opening, Closing) when H =:= "{" ->
    is_balanced(T, Opening + 1, Closing);
is_balanced([H | T], Opening, Closing) when H =:= "}" ->
    is_balanced(T, Opening, Closing + 1);
is_balanced([], Opening, Closing) -> (Opening - Closing).

计算字符串中右大括号和左大括号的数量的非常基本的代码。

在 Erlang shell 中,当我尝试调用函数 is_balanced 时: balanced_brackets:is_balanced("{}").

输出以下错误:

** exception error: no function clause matching balanced_brackets:is_balanced("{}",0,0) (balanced_brackets.erl, line 7)

但是,如果我将参数作为显式列表传递,则模式匹配可以正常工作: balanced_brackets:is_balanced(["{", "}"]).

Erlang 字符串不是简单地在内部列出吗?为什么使用构造模式匹配字符串是不正确的[H | T]

执行 BIFis_list("{}").返回true

我真诚地感谢有人对例外的解释。

谢谢你。

Erlang/OTP 17 [erts-6.2] [source-aaaefb3] [64-bit] [smp:2:2] [async-threads:10] [hipe] [kernel-poll:false]

4

2 回答 2

2

问题是你的保护定义,你正在比较"{"哪个是[123],即一个元素代表的列表{

你的模式匹配是正确的,但你会想要匹配123而不是"{"}当然也一样)。

修复代码(并保持其可读性)的最简单方法是比较[H]而不是H在守卫中:

is_balanced([H | T], Opening, Closing) when [H] =:= "{" ->
    is_balanced(T, Opening + 1, Closing);
于 2014-12-20T15:41:31.147 回答
2

无需使用数字来表示此答案中建议的字符。相反,只需使用 Erlang 字符常量。例如,要表示{字符,您可以使用${.

修复代码的一个好方法是完全避免守卫,只匹配函数头中的字符,如下所示${$}

is_balanced([${ | T], Opening, Closing) ->
    is_balanced(T, Opening + 1, Closing);
is_balanced([$} | T], Opening, Closing) ->
    is_balanced(T, Opening, Closing + 1);

然后,您需要另一个子句来处理原始代码中缺少的${and以外的字符:$}

is_balanced([_ | T], Opening, Closing) ->
    is_balanced(T, Opening, Closing);

最后,保留原来的 final 子句来处理空列表,结束递归:

is_balanced([], Opening, Closing) -> (Opening - Closing).

还有一件事:给定函数名称is_balanced,它似乎想要返回一个布尔值。如果是这样,请将顶部函数更改为:

is_balanced(String) -> is_balanced(String, 0, 0) == 0.
于 2014-12-20T22:45:47.130 回答