这是99 Lisp problems中的#7:通过将每个列表替换为其元素(递归地),将列表转换为“平面”列表,从而将列表转换为元素。我尝试了几种解决方案,例如来自#2680864或from here。它们都有效,但如果我展平包含带引号的元素的列表,我会遇到问题。 E.g:
> '(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,......他们都表现得一样。
答案 0 :(得分:2)
列表中的引用元素?这通常没有意义。你为什么要引用它?
(a b c)
是三个符号的列表。为什么要引用列表中的元素?在(a 'b c)
中?为什么?报价的目的是什么?
在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))