2014-12-20 45 views
1

我最近開始研究Erlang並遇到了一個我無法解釋的奇怪異常。模式匹配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). 

非常基本的代碼,以計算一個串關閉和打開大括號的數目。

在二郎殼,當我嘗試調用的函數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字符串只是簡單地列出inte rnally?爲什麼模式匹配使用構造[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]

回答

1

的問題是你的守護定義,你是比較"{"這是[123],即帶有一個元素代表{名單。

您的圖案匹配是正確的,但您希望匹配123而不是"{"(當然,}也是如此)。

修復您的代碼(並保持其可讀)最簡單的方法是比較[H],而不是H在後衛:

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

就是這樣!謝謝你的簡潔解釋。標記爲已接受。 – user3813812

+0

,或者您可以將H與$ {比較,以另一種方式表示123,但將其顯示爲字符。 – Pascal

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); 

最後,保持原有的最終條款來處理空列表,結束遞歸:

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

還有一件事:給定函數名is_balanced,它似乎想要返回一個布爾值。如果是這樣,請將頂部功能更改爲:

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