triangle-recursively関数で何が起こるのか、改めて考えてみましょう。中間計算は、すべて完了するまで延期されることがわかります。
関数の定義は以下の通りです。
(defun triangle-recursively (number) "Return the sum of the numbers 1 through NUMBER inclusive. Uses recursion." (if (= number 1) ; do-again-test 1 ; then-part (+ number ; else-part (triangle-recursively ; recursive call (1- number))))) ; next-step-expression
この関数に引数7を渡して呼び出すと、どうなるでしょうか?
triangle-recursively 関数の最初のインスタンスは、引数 6 が渡された
triangle-recursively の2番目のインスタンスが返す値に数値 7
を加算します。つまり、最初の計算は次のようになります。
(+ 7 (triangle-recursively 6))
triangle-recursivelyの最初のインスタンス――小さなロボットのようなものと考えてよいでしょう――は、自身の処理を完了することができません。そのため、(triangle-recursively
6)の計算をプログラムの2番目のインスタンス、つまり2台目のロボットに引き継がなければなりません。この2台目の個体は、1台目とは全く別物です。専門用語で言えば、「別のインスタンス化」にあたります。言い換えれば、別のロボットということです。モデルは1台目と同じで、三角数を再帰的に計算しますが、シリアル番号が異なります。
では、(triangle-recursively
6)は何を返すのでしょうか?それは、引数5を指定してtriangle-recursivelyを評価して得られた値に6を加えた数値を返します。ロボットの比喩で言えば、また別のロボットに助けを求めていることになります。
これで合計は:
(+ 7 6 (triangle-recursively 5))
それで、この後はどうなるの?
(+ 7 6 5 (triangle-recursively 4))
triangle-recursivelyが呼び出されるたびに、最後の一回を除いて、プログラムの別のインスタンス—別のロボット—を生成し、計算を行わせる。
最終的に、加算処理全体がセットアップされ、実行されます:
(+ 7 6 5 4 3 2 1)
この関数の設計では、最初のステップの計算を2番目のステップが可能になるまで延期し、さらにそれを3番目のステップが可能になるまで延期する、という具合に繰り返されます。延期が行われるたびに、コンピュータは何を待っているのかを記憶しておく必要があります。この例のようにステップ数が少ない場合は問題になりません。しかし、ステップ数が多くなると問題になる可能性があります。