Erlangは、関数型プログラミング言語に共通する機能である関数内に副作用を持たせることはできません。可変状態の変更は副作用です。Erlangの状態変化はすべて、プロセスとメッセージパッシングによって隠されています。これはいわゆるアクターモデルです。
変数を「変更」する一般的な方法は、関数が変更された変数を使用して自分自身を呼び出すことです。これは再帰と呼ばれます。たとえば、リストのすべての要素を合計するには、次のようにします。
sum([]) -> 0;
sum([H|Tail]) -> H + sum(Tail).
さらに良いのは、関数の末尾再帰を作成することです。これは、関数が関数本体の最後の命令として自分自身を呼び出すことを意味します。すべての関数呼び出しをスタックに保持する必要がないため、メモリを節約できます(末尾呼び出しの最適化)。同じ例ですが、末尾再帰を使用しています。
sum([], Acc) -> Acc;
sum([H|Tail], Acc) -> sum(Tail, Acc + H).
sum(L) -> sum(L, 0).
この例では、中間結果を渡すためにアキュムレータ変数を導入しました。
プログラムの副作用をなくす方法は必ずしも明らかではありません。特に、(CやJavaのように)手続き的な用語で問題を考えようとする場合はそうです。より理論的なレベルで関数型プログラミングを理解するには、練習とおそらく意志が必要です。
純粋に関数型プログラミング言語には、副作用はまったくありません。関数の戻り値は、関数の入力引数のみに基づいている必要があり、関数からの出力は戻り値のみである必要があります。これはErlangには当てはまりません。recieve
句と!
演算子は、関数内の入力と出力に使用されます。副作用。外部状態は、メッセージを送信して応答を取得できるプロセスとして保持できます。
メッセージパッシングによって値を変更できる変数を作成する方法の例を次に示します(var_proc
末尾再帰であるかどうかを確認してください)。
var_proc(Value) ->
receive
{get, Pid} ->
Pid ! {value, Value},
var_proc(Value);
{set, New} ->
var_proc(New)
end.
var_start(Init) ->
spawn(?MODULE, var_proc, [Init]).
var_set(Pid, Value) ->
Pid ! {set, Value}.
var_get(Pid) ->
Pid ! {get, self()},
receive
{value, Value} -> Value
end.
これを使用する方法の例を次に示します(私はモジュールを「合計」と呼んでいます)。
13> V = sum:var_start(6).
<0.72.0>
14> sum:var_get(V).
6
15> sum:var_set(V, 10).
{set,10}
16> sum:var_get(V).
10
その他の例といくつかの動機は、Erlangドキュメントの並行プログラミングの章にあります。