どちらの関数もネストされたcons
で動作します。 '(1 2 3)
は、(1 . (2 . (3 .()))
と(cons 1 (cons 2 (cons 3 '())))
です。ネストされたリストは、にcons
がネストされていることです。cons
です。例えば。 ((1 .()) .()) ; ==> ((1))
。
それは((1) (2 3))
を見て、あなたが3
にアクセスする場合、それは明らかにパスd、D、Aだと逆にあなたがアクセサcadadr
を構築することができるように、それは((1 .()) . ((2 . (3 .())) .()))
であることを理解することが重要です。
cons
cons
は、car
の部分が木である。木を歩く関数を作成するときは、とcdr
の両方を歩く必要がある場合は、cons
です。したがって:
;; generic function to walk trees and reduce
;; by combiner every value accessed by term
;; the default argument to combiner is tree-null
(defun accumulate-tree (tree term combiner null-value)
(labels ((rec (tree)
(cond ((null tree) null-value)
((atom tree) (funcall term tree))
(t (funcall combiner (rec (car tree))
(rec (cdr tree)))))))
(rec tree)))
(defun sum-numbers (tree)
(accumulate-tree tree
#'identity
#'+
0))
(defun count-numbers (tree)
(accumulate-tree tree
(lambda (v) (if (numberp v) 1 0))
#'+
0))
(sum-numbers '((1) (2 3) (((4)) 5))) ; ==> 15
(count-numbers '(a b 4 3 (e f 5) . 9)) ; ==> 4
コンバイナは、原子に削減する必要がありません:
(defun reverse-tree (tree)
(accumulate-tree tree
#'identity
(lambda (a d) (cons d a))
'()))
(reverse-tree '((1 2) (3 4)))
; ==> ((nil (nil . 4) . 3) (nil . 2) . 1)
あなたの関数のインデントを修正してください。そのためにEmacsを使うことができます。彼らが今提示されているので、あなたのコードはlisperに読めません。ありがとうございました。 – sds