ここまでは良い答えがいくつかありますが、もう1つ、別の方法で説明します。
最初に、私はあなたが興味深いと思うかもしれない単純な再帰的アルゴリズムに関する多くの記事を書きました。見る
http://ericlippert.com/tag/recursion/
http://blogs.msdn.com/b/ericlippert/archive/tags/recursion/
これらは最新のものから順に並んでいるので、下から始めます。
第二に、これまでのところ、すべての回答は、関数のアクティブ化を検討することにより、再帰的なセマンティクスを説明しています。つまり、各呼び出しは新しいアクティベーションを行い、再帰呼び出しはこのアクティベーションのコンテキストで実行されます。それはそれを考える良い方法ですが、同等の別の方法があります。それは、スマートテキストの検索と置換です。
関数をもう少しコンパクトな形式に書き直してみましょう。これを特定の言語であると考えないでください。
s = (a, b) => a > b ? 0 : a + s(a + 1, b)
私はそれが理にかなっていると思います。条件演算子に慣れていない場合、それは形式でcondition ? consequence : alternative
あり、その意味は明らかになります。
次にs(2,5)
、呼び出しをテキストで関数本体に置き換え、次にa
with 2
およびb
withを置き換えることで評価し5
ます。
s(2, 5)
---> 2 > 5 ? 0 : 2 + s(2 + 1, 5)
次に条件を評価します。私たちは、テキストで置き換える2 > 5
とfalse
。
---> false ? 0 : 2 + s(2 + 1, 5)
今度は、すべての偽の条件文を代替テキストで置き換え、すべての真の条件文を結果で置き換えます。誤った条件文しかないため、テキストでその式を代替に置き換えます。
---> 2 + s(2 + 1, 5)
これらの+
記号をすべて入力する手間を省くために、定数演算をテキストでその値に置き換えます。(これは多少のごまかしですが、すべての括弧を追跡する必要はありません!)
---> 2 + s(3, 5)
次に、検索と置換を行います。今回は、b 、3
for a
、5
forの呼び出しの本文を使用します。呼び出しの代わりを括弧で囲みます。
---> 2 + (3 > 5 ? 0 : 3 + s(3 + 1, 5))
そして今、私たちは同じテキスト置換ステップを続けます:
---> 2 + (false ? 0 : 3 + s(3 + 1, 5))
---> 2 + (3 + s(3 + 1, 5))
---> 2 + (3 + s(4, 5))
---> 2 + (3 + (4 > 5 ? 0 : 4 + s(4 + 1, 5)))
---> 2 + (3 + (false ? 0 : 4 + s(4 + 1, 5)))
---> 2 + (3 + (4 + s(4 + 1, 5)))
---> 2 + (3 + (4 + s(5, 5)))
---> 2 + (3 + (4 + (5 > 5 ? 0 : 5 + s(5 + 1, 5))))
---> 2 + (3 + (4 + (false ? 0 : 5 + s(5 + 1, 5))))
---> 2 + (3 + (4 + (5 + s(5 + 1, 5))))
---> 2 + (3 + (4 + (5 + s(6, 5))))
---> 2 + (3 + (4 + (5 + (6 > 5 ? 0 : s(6 + 1, 5)))))
---> 2 + (3 + (4 + (5 + (true ? 0 : s(6 + 1, 5)))))
---> 2 + (3 + (4 + (5 + 0)))
---> 2 + (3 + (4 + 5))
---> 2 + (3 + 9)
---> 2 + 12
---> 14
ここで行ったのは、単純なテキスト置換だけでした。本当に、私は "2 + 1"の代わりに "3"を使うべきではありませんでした。
関数のアクティブ化は、関数呼び出しを呼び出しの本体で置き換え、仮パラメーターを対応する引数で置き換えることに他なりません。かっこをインテリジェントに導入するように注意する必要がありますが、それを除けば、それは単なるテキスト置換です。
もちろん、ほとんどの言語は実際にはテキスト置換としてアクティベーションを実装していませんが、論理的にはそれがそうです。
では、無限の再帰とは何でしょうか。テキストの置換が止まらない再帰!最終的にs
、置き換える必要のないステップに到達し、算術のルールを適用できることに注目してください。