Erlang コードを書いているときに、理解できない奇妙な状況に遭遇しました。
コード:
-module(recursive_test).
-export([a/2]).
a(_, []) -> ok;
a(Args, [H|T]) ->
F = fun() -> a(Args, T) end,
io:fwrite(
"~nH: ~p~nStack Layers: ~p",
[H, process_info(self(), stack_size)]
),
b(Args, F).
b(Args, F) ->
case Args of
true -> ok;
false -> F()
end.
出力:
(Erlang/OTP 20)
12> c(recursive_test).
{ok,recursive_test}
13> recursive_test:a(false, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]).
H: 1
Stack Layers: 28
H: 2
Stack Layers: 28
H: 3
Stack Layers: 28
H: 4
Stack Layers: 28
H: 5
Stack Layers: 28
H: 6
Stack Layers: 28
H: 7
Stack Layers: 28
H: 8
Stack Layers: 28
H: 9
Stack Layers: 28
H: 10
Stack Layers: 28
ok
14> recursive_test:a(false, [1, 2, 3, 4, 5, 6]).
H: 1
Stack Layers: 28
H: 2
Stack Layers: 28
H: 3
Stack Layers: 28
H: 4
Stack Layers: 28
H: 5
Stack Layers: 28
H: 6
Stack Layers: 28
ok
この記事から私が理解していることから、Erlang は Last Call Optimization を使用します。関数が最後に行うことが別の関数を呼び出すことである場合、BeamVM は代わりに、新しいスタックをプッシュする代わりに、プログラム カウンターを新しい関数の先頭にジャンプします。フレーム。これは、上記のようなパターンでは、スタックではなくヒープを処理していることを意味するのでしょうか? これにより、これらの関数で以前に保持されていたメモリが解放されますか?時間)?このパターンを使用すると、(明らかなデバッグの苦労以外に) 悪影響はありますか?