Menggunakan "printf debugging"
Anda dapat membiarkan Emacs membantu Anda memahami dengan memodifikasi definisi fungsi:
(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))))))
Cukup tambahkan (message ...)
tempat untuk membuat jejak dicetak ke *Messages*
buffer.
Menggunakan Edebug
Tempatkan titik di mana saja di dalam definisi fungsi dan tekan C-u C-M-x
untuk "instrumen" itu. Kemudian evaluasi fungsi, misalnya dengan menempatkan titik setelah (triangle-using-cond 3)
dan memukul C-x C-e
.
Anda sekarang dalam mode Edebug. Tekan bilah spasi untuk melangkah melalui fungsi. Nilai menengah dari setiap ekspresi ditampilkan di area gema. Untuk keluar dari mode Edebug, tekan saja q
. Untuk menghapus instrumentasi, beri titik di mana saja di dalam definisi dan tekan C-M-x
untuk mengevaluasi kembali definisi.
Menggunakan debugger Emacs standar
M-x debug-on-entry triangle-using-cond
, kemudian, ketika triangle-using-cond
dipanggil, Anda ditempatkan di debugger Emacs (buffer *Backtrace*
).
Langkah melalui evaluasi menggunakan d
(atau c
untuk melewati evaluasi yang tidak menarik).
Untuk melihat kondisi antara (nilai variabel, dll.) Anda dapat menggunakan e
kapan saja. Anda diminta memasukkan sexp untuk mengevaluasi, dan hasil evaluasi dicetak.
Saat Anda menggunakan debugger, buat salinan kode sumber terlihat di frame lain, sehingga Anda dapat mengikuti apa yang terjadi.
Anda juga dapat memasukkan panggilan eksplisit untuk memasukkan debugger (lebih atau kurang breakpoints) di tempat sewenang-wenang dalam kode sumber. Anda memasukkan (debug)
atau (debug nil SOME-SEXP-TO-EVALUATE)
. Dalam kasus terakhir, ketika debugger dimasukkan SOME-SEXP-TO-EVALUATE
dievaluasi dan hasilnya dicetak. (Ingatlah bahwa Anda dapat memasukkan kode seperti itu ke dalam kode sumber dan menggunakannya C-M-x
untuk mengevaluasinya, lalu batalkan - Anda tidak perlu menyimpan file yang diedit.)
Lihat manual Elisp, simpul Using Debugger
untuk informasi lebih lanjut.
Rekursi sebagai lingkaran
Bagaimanapun, anggap rekursi sebagai satu lingkaran. Ada dua kasus terminasi yang didefinisikan: (<= number 0)
dan (= number 1)
. Dalam kasus ini fungsi mengembalikan angka sederhana.
Dalam kasus rekursif fungsi mengembalikan jumlah dari angka itu dan hasil dari fungsi dengan number - 1
. Akhirnya, fungsi akan dipanggil dengan salah satu 1
atau nomor yang lebih kecil dari atau sama dengan nol.
Karenanya, hasil kasus rekursif adalah:
(+ number (+ (1- number) (+ (1- (1- number)) ... 1)
Ambil contoh (triangle-using-cond 4)
. Mari kita akumulasikan ekspresi terakhir:
di iterasi pertama number
adalah 4
, sehingga (> number 1)
cabang diikuti. Kami mulai membangun ekspresi (+ 4 ...
dan memanggil fungsi dengan (1- 4)
, yaitu (triangle-using-cond 3)
.
sekarang number
adalah 3
, dan hasilnya adalah (+ 3 (triangle-using-cond 2))
. Ekspresi hasil total adalah (+ 4 (+ 3 (triangle-using-cond 2)))
.
number
adalah 2
sekarang, jadi ekspresi adalah(+ 4 (+ 3 (+ 2 (triangle-using-cond 1))))
number
adalah 1
sekarang, dan kita mengambil (= number 1)
cabang, sehingga membosankan sebuah 1
. Seluruh ekspresi itu (+ 4 (+ 3 (+ 2 1)))
. Evaluasi yang dari dalam ke luar dan Anda mendapatkan: (+ 4 (+ 3 3))
, (+ 4 6)
, atau hanya 10
.
triangle-using-cond
dengan argumen menjadi 1 kurang dari apa pun jumlahnya. Kondisi berjalan dalam urutan a, b, dan kemudian c - apa pun yang cocok terlebih dahulu, adalah di mana uang berhenti.