比如, delete
是 remove
的一个具有破坏性的版本。虽然它可以破坏作为参数传给它的列表,但它并不保证什么。在大多数的 Common Lisp 的实现中,会出现下面的情况:
正如 remove
一样,如果你想要副作用,应该对返回值使用 setf
:
(setf lst (delete 'a lst))
破坏性函数是怎样回收利用传给它们的列表的呢?比如,可以考虑 nconc
—— append
的破坏性版本。[2]下面是两个参数版本的实现,其清楚地展示了两个已知列表是怎样被缝在一起的:
函数 类似 mapcar
,但它是用 nconc
把函数的返回值 (必须是列表) 拼接在一起的:
> (mapcan #'list
'(a b c)
( A 1 B 2 C 3)
这个函数可以定义如下:
使用 mapcan
时要谨慎,因为它具有破坏性。它用 nconc
拼接返回的列表,所以这些列表最好不要再在其它地方使用。
(mapcan #'(lambda (c)
(children x)))
这个函数调用 copy-list
时存在一个假设 —— chlidren
函数返回的是一个已经保存在某个地方的列表,而不是构建了一个新的列表。
一个 mapcan
的无损变体可以这样定义:
如果使用 mappend
函数,那么 grandchildren
的定义就可以省去 copy-list
:
(mappend #'children (children x)))