Common Lisp的 - 平光可能包含符号列表(Common Lisp - flatting a

2019-07-29 10:39发布

这是#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,......他们的行为都以同样的方式。

Answer 1:

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

(abc)是三个符号的列表。 为什么你会引用列表中的元素? 就像在(a 'bc) 为什么? 什么是报价的目的是什么?

Common Lisp中'是膨胀的readmacro 'a(QUOTE A) 由于这是一个正常的列表,一个典型的扁平化操作将收集符号QUOTEA到平面列表。 这是因为扁平化功能。典型检查是否某物是原子或没有。 如果你不希望这样,你的扁平化功能需要检查,如果事情是原子或具有两个元素的列表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))


文章来源: Common Lisp - flatting a list that may contain symbols