javascriptすごいE本の「再帰さん、こんにちは!」を読んでて、末尾再帰のところが理解できなかったので調べた。基本的な再帰関数duplicate/2以下は整数の第二引数の項を第一引数の数だけコピーしたリストを作る関数。overflowになる。多くのメモリを消費する。これを改善するために末尾再帰をやってみよう!というのが以下。末尾再帰にしたduplicate/2末尾再帰にするとこうなる。(書籍は関数名をtail_duplicateにしているけど、ここではduplicatenのままとする。[Term|List])].ここで思ったのは、Listという一時変数(アキュムレータ)を渡すことで呼び出した関数の結果に依存することはなくなるんだろうけど、結局関数呼んでるわけだしスタック消費するじゃん!、と。これは「末尾呼び出しの最適化」なるものがかかっているらしく、こいつを頭に入れることでようやく理解できた。この記事が分かりやすかった。bleis-tift.hatenablog.com末尾呼び出しというのは、関数を呼び出した後に結果を戻す以外にすることがないような関数呼び出しのことを言います末尾呼び出しは「関数から戻ってきた後に結果を戻す以外にすることがないような関数呼び出し」でした。いうのが末尾呼び出しの最適化ですなるほど。ここまで書いて理解できたから先に行こうと読み進めたら、ちゃんと書いてあった。ゆかいに学ぼう!」59頁より)なぜなら仮想マシンは、関数が自分自身を末尾(関数内で評価される最後の式)で呼び出していたら、現在のスタックフレームを削除するからです。あと、このようにも書いてある。a().のような関数の連鎖があるとします。これはLCO(終端呼び出し最適化)がスタックのオーバーフローを避けるので、メモリが枯渇しない無限ループを効率的に生成します。JavaScriptでは?どうなってるのか気になったので調べてみた。teppeis.hatenablog.comどうやら2015年になってからBabelに末尾再帰最適化が入ったらしい。list.unshift(term));}これをバベる。}}参考記事と同様にwhileに変換されていることが確認された。12引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。