あなたはあなたの括弧をすべてごちゃ混ぜにしました:
(defun stable-union (x y)
(cond
((null x) y)
((null y) x) ) END OF COND form - has no effect
(do ((i y (cdr i))
^^
(lst3 x (append lst3
(cond
((listp i)
( (null (member (car i) lst3))
^^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ called as a function
(cons (car i) nil) with two arguments
nil ) )
^^
(t NEXT 3 forms have no effect
(null (member i lst3))
(cons i nil)
nil )))) )
^^
((null (cdr i)) lst3)))
おそらく意図したとおりのコードです。括弧を修正し、必要に応じていくつかif
の s を追加しています。
(defun stable-union (x y)
(cond
((null x) y)
((null y) x)
(t
(do ((i y (cdr i))
(lst3 x (append lst3
(cond
((listp i)
(if (null (member (car i) lst3))
(cons (car i) nil)
nil))
(t
(if (null (member i lst3))
(cons i nil)
nil))))))
((null (cdr i)) lst3)))))
このコードにはまだ問題があります。ロジックdo
が間違っていますy
。要素が 1 つしか含まれていない場合、最初の要素をスキップします。そしてappend
、必要かどうかにかかわらず、常に電話をかけます。を呼び出す(append lst3 nil)
と、 のトップレベルのコンス セルのコピーが作成されることに注意してくださいlst3
。
あなたが持っているような長いステートメントは、通常、のローカル変数のdo
更新フォーム内ではなく、本体に配置されます。do
ただし、必要に応じて、より特殊な形式の を使用できますdo
。ここでは を使用するのが自然dolist
です。メンバーシップ テストにハッシュ テーブルを使用することに関する "wvxvw" のリードに従って、次のように記述します。
(defun stable-union (a b &aux (z (list nil)))
(let ((h (make-hash-table))
(p z))
(dolist (i a)
(unless (gethash i h)
(setf (cdr p) (list i) p (cdr p))
(setf (gethash i h) t)))
(dolist (i b (cdr z))
(unless (gethash i h)
(setf (cdr p) (list i) p (cdr p))
(setf (gethash i h) t)))))
私が「head-sentinel」(シングルトン リストに事前に初期化された変数) と呼んでいる手法を使用すると、余分なセルz
を 1 つ割り当てる代償を払って、トップダウン リスト構築のコードを大幅に簡素化できます。cons