common-lisp
再帰
サーチ…
備考
Lispは、教育的な文脈でよく使われます。ここでは、再帰的なアルゴリズムを理解し実装する方法を学びます。
Common Lispや移植可能なコードで書かれたプロダクションコードには、再帰に関するいくつかの問題があります。 テールコールの最適化などの実装固有の機能を使用せず、しばしば再帰を避ける必要があります。これらの場合、実装は次のとおりです。
- 通常、スタックサイズの制限により、 再帰の深さ制限があります。したがって、再帰的アルゴリズムは、限られたサイズのデータに対してのみ機能します。
- テールコールの最適化を常に提供するとは限りません。
- 特定の最適化レベルでテールコールの最適化のみを提供します。
- 通常、 テールコールの最適化を提供しないでください。
- 通常、特定のプラットフォームでテールコールの最適化を提供しません。たとえば、JVM上の実装では、JVM自体がテールコールの最適化をサポートしていないため、JVM上の実装では実装できません。
テールコールをジャンプで置き換えると、通常はデバッグが難しくなります。ジャンプを追加すると、スタックフレームがデバッガで使用できなくなります。代わりに、Common Lispは以下を提供します:
-
DO
、DOTIMES
、LOOP
などの反復構造 -
MAP
、REDUCE
などの高次関数 - 低レベルを含む様々な制御構造は、
go to
再帰テンプレート2のマルチコンディション
(defun fn (x)
(cond (test-condition1 the-value1)
(test-condition2 the-value2)
...
...
...
(t (fn reduced-argument-x))))
CL-USER 2788 > (defun my-fib (n)
(cond ((= n 1) 1)
((= n 2) 1)
(t (+
(my-fib (- n 1))
(my-fib (- n 2))))))
MY-FIB
CL-USER 2789 > (my-fib 1)
1
CL-USER 2790 > (my-fib 2)
1
CL-USER 2791 > (my-fib 3)
2
CL-USER 2792 > (my-fib 4)
3
CL-USER 2793 > (my-fib 5)
5
CL-USER 2794 > (my-fib 6)
8
CL-USER 2795 > (my-fib 7)
13
再帰テンプレート1つの条件単一テール再帰
(defun fn (x)
(cond (test-condition the-value)
(t (fn reduced-argument-x))))
フィボナッチ数を計算する
;;Find the nth Fibonacci number for any n > 0.
;; Precondition: n > 0, n is an integer. Behavior undefined otherwise.
(defun fibonacci (n)
(cond
( ;; Base case.
;; The first two Fibonacci numbers (indices 1 and 2) are 1 by definition.
(<= n 2) ;; If n <= 2
1 ;; then return 1.
)
(t ;; else
(+ ;; return the sum of
;; the results of calling
(fibonacci (- n 1)) ;; fibonacci(n-1) and
(fibonacci (- n 2)) ;; fibonacci(n-2).
;; This is the recursive case.
)
)
)
)
リストの要素を再帰的に出力する
;;Recursively print the elements of a list
(defun print-list (elements)
(cond
((null elements) '()) ;; Base case: There are no elements that have yet to be printed. Don't do anything and return a null list.
(t
;; Recursive case
;; Print the next element.
(write-line (write-to-string (car elements)))
;; Recurse on the rest of the list.
(print-list (cdr elements))
)
)
)
これをテストするには、以下を実行します。
(setq test-list '(1 2 3 4))
(print-list test-list)
結果は次のようになります。
1
2
3
4
整数の階乗を計算する
再帰関数として実装する簡単なアルゴリズムの1つが階乗です。
;;Compute the factorial for any n >= 0. Precondition: n >= 0, n is an integer.
(defun factorial (n)
(cond
((= n 0) 1) ;; Special case, 0! = 1
((= n 1) 1) ;; Base case, 1! = 1
(t
;; Recursive case
;; Multiply n by the factorial of n - 1.
(* n (factorial (- n 1)))
)
)
)
Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow