「printfデバッグ」を使用する
関数定義を変更することで、Emacsに理解を助けてもらうことができます。
(defun triangle-using-cond (number)
(message (format "called with %d" number))
(cond ((<= number 0) 0)
((= number 1) 1)
((> number 1)
(+ number (triangle-using-cond (1- number))))))
バッファーに(message ...)
証跡を出力する場所を追加してください*Messages*
。
Edebugを使用する
関数定義内の任意の場所にポイントを置き、ヒットC-u C-M-x
して「計測」します。そして、後にポイントを置くことによって、機能、例えばを評価(triangle-using-cond 3)
して打ちますC-x C-e
。
これで、Edebugモードになりました。スペースバーを押して、機能をステップスルーします。各式の中間値がエコー領域に表示されます。Edebugモードを終了するには、を押してくださいq
。インストルメンテーションを削除するには、定義内の任意の場所にポイントを置き、ヒットC-M-x
して定義を再評価します。
標準のEmacsデバッガーを使用する
M-x debug-on-entry triangle-using-cond
、その後、triangle-using-cond
が呼び出されると、Emacsデバッガー(バッファー*Backtrace*
)に配置されます。
を使用して評価をステップ実行しますd
(またはc
、興味のない評価をスキップします)。
中間状態(変数値など)を表示するには、e
いつでも使用できます。評価するためにsexpを入力するように求められ、評価結果が出力されます。
デバッガーを使用している間、ソースコードのコピーを別のフレームに表示しておくと、何が起こっているのかを追跡できます。
また、ソースコードの任意の場所で明示的な呼び出しを挿入して、デバッガー(多かれ少なかれブレークポイント)に入ることもできます。(debug)
またはを挿入し(debug nil SOME-SEXP-TO-EVALUATE)
ます。後者の場合、デバッガが入力SOME-SEXP-TO-EVALUATE
されると評価され、結果が出力されます。(このようなコードをソースコードに挿入し、C-M-x
評価に使用してから元に戻すことができます。編集したファイルを保存する必要はありません。)
詳細については、ElispマニュアルのノードUsing Debugger
を参照してください。
ループとしての再帰
とにかく、再帰をループと考えてください。定義されている2つの終了ケースがあります:(<= number 0)
と(= number 1)
。これらの場合、関数は単純な数値を返します。
再帰的な場合、関数はその数との関数の結果の合計を返しますnumber - 1
。最終的に、関数は1
ゼロ以下のいずれかまたは数字で呼び出されます。
したがって、再帰的なケースの結果は次のとおりです。
(+ number (+ (1- number) (+ (1- (1- number)) ... 1)
例を挙げましょう(triangle-using-cond 4)
。最終的な式を蓄積しましょう:
最初の反復でnumber
は4
であるため、(> number 1)
分岐が続きます。私たちは、表現の構築を開始(+ 4 ...
し、して関数を呼び出し(1- 4)
、すなわち(triangle-using-cond 3)
。
現在number
は3
であり、結果は(+ 3 (triangle-using-cond 2))
です。合計結果式は(+ 4 (+ 3 (triangle-using-cond 2)))
です。
number
ある2
式があるので、今(+ 4 (+ 3 (+ 2 (triangle-using-cond 1))))
number
があり1
、(= number 1)
分岐を取り、退屈になり1
ます。全体の表現は(+ 4 (+ 3 (+ 2 1)))
です。:内部から出ていることを評価し、あなたが得る(+ 4 (+ 3 3))
、(+ 4 6)
ちょうど、または10
。
triangle-using-cond
が返す値に数値を加算します。引数は数値より1小さい値です。条件は、a、b、cの順になります。最初に一致するものは何でも、降圧が停止します。