0

这是99 个 Lisp 问题中的第 7 个:通过将每个列表替换为其元素(递归地),将列表(可能将列表作为元素保存)转换为“平面”列表。我尝试了几种解决方案,例如从 # 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……它们的行为方式都相同。

4

1 回答 1

2

列表中的引用元素?这通常没有意义。你为什么要引用它?

(a b c)是三个符号的列表。为什么要引用列表中的元素?喜欢在(a 'b c)?为什么?引用的目的是什么?

在 Common Lisp'中是一个扩展'a(QUOTE A). 由于这是一个普通列表,典型的展平操作会将符号收集到展QUOTEA列表中。这是因为 flatten 函数通常会检查某物是否为原子。如果你不想要这个,你的 flatten 函数需要检查某个东西是一个原子还是一个二元素列表,QUOTE它的第一个符号是。

但正如我上面所说,默认用法只是扁平化符号,因为引用的符号通常在列表中没有用。否则,您需要扩展 flatten 功能。

例如:

(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))
于 2012-05-17T17:27:42.123 回答