【问题标题】:Pattern match Erlang string as list in function模式匹配 Erlang 字符串作为函数中的列表
【发布时间】:2015-02-19 07:25:51
【问题描述】:

我最近开始研究 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] 构造模式匹配字符串不正确?

执行 BIF is_list("{}"). 返回 true

我非常感谢有人对异常的解释。

谢谢。

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

【问题讨论】:

    标签: erlang erlang-shell


    【解决方案1】:

    问题在于您的保护定义,您正在与"{" 进行比较,即[123],即一个列表,其中一个元素代表{

    您的模式匹配是正确的,但您需要匹配123 而不是"{"(当然} 也是如此)。

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

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

    【讨论】:

    • 就是这样!感谢您的简洁解释。标记为已接受。
    • 或者您可以将 H 与 ${ 进行比较,这是表示 123 的另一种方式,但将其显示为字符。
    【解决方案2】:

    没有必要按照this answer 的建议使用数字来表示字符。相反,只需使用 Erlang 字符常量。例如,要表示{ 字符,您可以使用${

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

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

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

    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.
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-09-29
      • 1970-01-01
      • 1970-01-01
      • 2015-05-29
      • 2020-04-23
      • 2011-08-14
      • 1970-01-01
      • 2015-09-16
      相关资源
      最近更新 更多