这是#7 99个Lisp的问题 :通过用其元素(递归的)替换每个列表变换的列表,可能保持列表作为要素引入`平坦名单。 我尝试了好几种解决方案,例如从# 2680864或从这里 。 他们都工作,但我遇到一个问题,如果我压扁包含引用元素的列表。 例如:
> '(a 'b c)
(A 'B C)
> '(a (quote b) c)
(A 'B C)
> (flatten '(a 'b c))
(A QUOTE B C)
在后一种情况下,我想获得:
(A 'B C)
看来的“内部表示在此任务的方式获得! SBCL,CLISP,ECL,......他们的行为都以同样的方式。
引用列表中的元素呢? 这通常是没有意义的。 为什么你会拥有它引用?
(abc)
是三个符号的列表。 为什么你会引用列表中的元素? 就像在(a 'bc)
为什么? 什么是报价的目的是什么?
Common Lisp中'
是膨胀的readmacro 'a
为(QUOTE A)
由于这是一个正常的列表,一个典型的扁平化操作将收集符号QUOTE
和A
到平面列表。 这是因为扁平化功能。典型检查是否某物是原子或没有。 如果你不希望这样,你的扁平化功能需要检查,如果事情是原子或具有两个元素的列表QUOTE
作为其第一个符号。
但正如我上面所说的,默认的使用仅仅是扁平化的符号,因为符号的报价通常不是列表里面有用。 您需要,否则延长扁平化功能。
例如:
(defun flatten (l &key (test #'atom))
(cond ((null l) nil)
((funcall test l) (list l))
(t (loop for a in l nconc (flatten a :test test)))))
CL-USER > (flatten '(a (('b) c) ('d) )
:test (lambda (item)
(or (atom item)
(and (eq (first item) 'quote)
(null (cddr item))))))
(A (QUOTE B) C (QUOTE D))