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 シェルで関数 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]

4

2 に答える 2

2

問題はガードの定義です。つまり、 を表す 1 つの要素を持つリストと比較して"{"います。[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);

次に、元のコードにない${と以外の文字を処理する別の句が必要です。$}

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

最後に、空のリストを処理するために元の最終節を保持し、再帰を終了します。

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

もう 1 つ: 関数 nameis_balancedを指定すると、ブール値を返したいように見えます。その場合は、トップ関数を次のように変更します。

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