2017-04-03 14 views
0

私は宿題に取り組んでいます。最初の機能では、リストの特定の要素を削除したり、リストの特定の要素を表示したりしていました。次の関数では、ネストされたリストを削除したり、表示したりすることができます。ネストされたリストを扱うための一般的なヒントはありますか?私は、以前に書いたものと機能が非常に似ていると思ってちょっと微妙に微調整しました。LISPでネストされたリストを使用するにはどうすればいいですか?

これまでに書いた関数の2つの例を示します。注記関数を書くには "cond"スタイルを使わなければなりません。

(defun delnth(L A) 
    (cond ((= A 1) (rest L)) 
     (t (cons (first L) (delnth (rest L) (- A 1)))))) 


(defun remv(A L) 
    (cond ((eq A (first L)) (remv A (rest L))) 
     ((null L) nil) 
     (t (cons (first L) (remv A (rest L)))))) 
+1

あなたの関数のインデントを修正してください。そのためにEmacsを使うことができます。彼らが今提示されているので、あなたのコードはlisperに読めません。ありがとうございました。 – sds

答えて

1

どちらの関数もネストされた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 .())) .()))であることを理解することが重要です。

consconsは、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) 
関連する問題