3

私は Erlang で遊んでいて、S 式パーサーを書こうとしています。Python でスタックとループを使用するのは簡単な作業だと思いますが、不変変数と Erlang データ構造の初心者である私にとっては簡単なことではありません。

次のように Erlang でリストを変換する必要があります。

X = ["0", "(", "1", "2", "3", ")"],
Res = transform(X). % ["0", ["1", "2", "3"]]

今では、私はこれに来ました:

transform(List) ->
    lists:map(fun(X)->
                      case string:equal("(", X) of
                          %% recursive call with sublist of List from "(" to ")" as argument
                          true -> transform_to_list(Lack) 
                      end
              end, List).

サブリストを取得して引数Lackとして渡す方法がわかりません。私は正しい方向に進んでいますか?

4

2 に答える 2

5

これは、アキュムレータとパターン マッチングを使用して解決できます。

-module(t).
-export([transform/1]).

transform(List) ->
    transform(List, []).

transform([], Acc) ->
    lists:reverse(Acc);
transform(["("|T], Acc) ->
    transform(T, {[],Acc});
transform([")"|T], {L,{L2,Acc}}) ->
    transform(T, {[lists:reverse(L)|L2],Acc});
transform([")"|T], {L,Acc}) ->
    transform(T, [lists:reverse(L)|Acc]);
transform([H|T], {L,Acc}) ->
    transform(T, {[H|L],Acc});
transform([H|T], Acc) ->
    transform(T, [H|Acc]).

このtransform/1関数は、 の空のアキュムレータを設定するだけでtransform/2、すべての作業が完了します。

関数は、transform/2複数のパターン マッチング再帰句に分割されます。

  • 最初の句は、入力リストを使い果たした場合を処理し、単純に逆アキュムレータを返します。アイテムがアキュムレータにプッシュされるため、反転が必要であり、逆の順序になります。これは、Erlang やその他の関数型言語でよく見られるパターンです。

  • 2 番目の句"("は、新しいサブリストを開始する を認識します。これを処理するために、アキュムレータを 2 タプルに変更します。最初の項目はサブリスト アキュムレータで、2 番目の項目は古いアキュムレータです。

  • 3 番目と 4 番目の句")"は、サブリストを終了する handle です。3 番目の節は、accumulator がタプルでもある 2 番目の要素を保持するタプルである場合のためのものです。新しいサブリストを項目として前のサブリストに追加し、アキュムレータ タプルから 1 レベルをポップします。4 番目の句は、タプルの元のアキュムレータがリストである場合を処理し、元のアキュムレータの先頭に新しいサブリストを追加して、新しいアキュムレータ リストを形成します。

  • 5 番目と 6 番目の句は、グループ化演算子ではない入力項目を処理します。5 番目の節はアキュムレータがタプルの場合を処理し、6 番目の節はアキュムレータがリストの場合を処理します。

元の例でこれを実行すると、正しい答えが表示されます。

1> c(t).
{ok,t}
2> t:transform(["0", "(", "1", "2", "3", ")"]).
["0",["1","2","3"]]

ただし、ネストされたグループも処理できます。

3> t:transform(["0", "(", "11", "22", "(", "333", "444",
                "(", "5555", ")", "666", ")", "77", "88", ")", "9"]).
["0",["11","22",["333","444",["5555"],"666"],"77","88"],"9"]
于 2016-09-16T13:19:17.723 に答える