在我的日子里,而不是(loop for a in l appending (g a))
我们写的(mapcan #'g l)
。(apply #'append (mapcar #'g l))
这或多或少等同于:
(defun flatten (l)
(if l
(if (atom l)
(list l)
(mapcan #'flatten l))))
那么在这种情况下是什么意思呢?想象一下,您调用(flatten (list 1 2 3 4 5))
,即参数列表中只有原子。该列表中的每个原子都包含在一个列表中 - 成为一个单例 列表,(1) (2)
等等。然后它们都附加在一起,给我们返回......原始列表:
( 1 2 3 4 5 )
( (1) (2) (3) (4) (5) )
( 1 2 3 4 5 )
因此,展平原子列表是一种恒等运算(在 Common LISP 中,即#'identity
)。现在想象展平一个包含一些原子的列表以及一个原子列表。同样,列表的每个元素都被转换,然后它们都被附加在一起。正如我们刚刚看到的,原子列表保持原样。每个原子都包含在一个列表中。因此,追加将返回嵌套列表中两个级别上的所有原子,现在已展平:flatten
( 11 12 (1 2 3 4) 13 )
( (11) (12) (1 2 3 4) (13) )
( 11 12 1 2 3 4 13 )
依此类推,还有更多级别的嵌套。
NIL
s 作为列表中的元素会带来问题。NIL
是一个空列表,空列表不包含任何内容,因此不应贡献任何内容。但NIL
也是一个原子。所以我们为它做了一个特殊的例子,不要把它包含在一个单例列表中——让它保持原样,所以当它被附加时,它就会消失。