factorial のような関数を書く場合:
fac(Val) when is_integer(Val)->
Visit = fun (X, _F) when X < 2 ->
1;
(X, F) ->
X * F(X -1, F)
end,
Visit(Val, Visit).
テール コールの最適化は単純ではありませんが、継続解析スタイルで記述すると次のようになります。
fac_cps(Val) when is_integer(Val)->
Visit = fun (X, _F, K) when X < 2 ->
K (1);
(X, F, K) ->
F(X-1, F, fun (Y) -> K(X * Y) end)
end,
Visit(Val, Visit, fun (X) -> X end).
または、おそらく非機能化されたもの:
fac_cps_def_lambdas({lam0}, X) ->
X;
fac_cps_def_lambdas({lam1, X, K}, Y) ->
fac_cps_def_lambdas(K, X*Y).
fac_cps_def(X) when is_integer(X) ->
fac_cps_def(X, {lam0}).
fac_cps_def(X, K) when X < 2 ->
fac_cps_def_lambdas(K,1);
fac_cps_def(X, K) ->
fac_cps_def(X-1, {lam1, X, K}).
これら 3 つの実装のタイミングを計ると、実行時間は予想どおり同じであることがわかりました。
私の質問は、これよりも詳細な知識を得る方法はありますか? たとえば、関数を実行する際のメモリ使用量を取得するにはどうすればよいですか?スタック メモリをまったく使用しないようにしていますか?
この種のものを検査するための標準的なツールは何ですか?
質問は、関数のスタックの高さをどのように測定するか、それぞれの関数呼び出しのメモリ使用量をどのように判断するか、そして最後にどれが最適かということです。