再帰関数を引数に取る高階関数を書いていたのですが、ちょっとつまづきました。
試行錯誤の上、動くもの自体は出来たのですが、自分の考えた対策は変数巻き上げを使わないといけないため、あまり読み手(将来の自分)にとって分かりづらいなと感じています。
それを変数巻き上げを使わずに別のより読み手に分かりやすい方法で行えないかと思っております。
言葉での説明が上手く出来そうにないので、質問用に用意した簡易的なコードで説明をいたします。
※極力、ES6を使わずに書きました。
高階関数に渡す関数
function func(n) { if (!n) return; console.log('#'.repeat(n)); newFunc(--n); } func(5); ##### #### ### ## #
単純に#を関数の引数に渡された数だけ出力するという処理を引数が0になるまで繰り返すというものです。
高階関数
function hof(fn) { const hr = '-----' return function inner() { console.log(hr); const args = Array.prototype.slice.apply(arguments); fn.apply(this, args); } } function func(n) { if (!n) return; console.log('#'.repeat(n)); newFunc(--n); //★関数スコープ外のnewFuncを参照 } const newFunc = hof(func); newFunc(5); ----- ##### ----- #### ----- ### ----- ## ----- # -----
質問用に用意した簡易的なコードのため、機能としては意味がないですが、
単純に区切り線を追加する高階関数です。
このコード自体は期待した動作をします。
でも、本当はこうしたかった
function func(n) { if (!n) return; console.log('#'.repeat(n)); func(--n); //★これだと元の`func`を再帰実行してしまう! } const newFunc = hof(func); newFunc(5); ----- ##### #### ### ## #
こちらの方が読み手にとって直感的で分かりやすいと思うのですが、、、
出力される結果は期待通りのものにはなりません。
原因はコード内のコメントに記した通りです。
そのため、最初に載せた高階関数のコードにたどり着いたのですが、やはり、外のスコープの変数を参照しているということと、変数の巻き上げを使っているというところで、僕的には読みづらいと感じてしまいます。
特に実際のコードはこれよりも長い為。
こういう場合は、何か出来る対策はあるのでしょうか?
補足
質問に掲載しているサンプルコードは、表題のことを示す以外の意味はありません。
そのため、「サンプルコードの場合であれば、再帰をつかなくてもこう出来る、高階関数使わなくてもこう出来る」のような話ではなく、以下の条件を前提とした質問となります。
- 再帰処理が行われる
- その再帰関数(fn1)を別の関数(fn2)の引数に渡して実行する
- 再帰関数(fn1)を渡す別の関数(fn2)のスコープにある変数を再帰関数(fn1)は参照する(キャッシュ等)
※別の例を挙げると、フィボナッチの再帰的に行う関数をメモ化したようなものをイメージするとわかりやすいかもしれません。
回答3件
あなたの回答
tips
プレビュー