我正在读 Paul Graham 写的《On Lisp》一书。在第 4 章“实用函数”中,他给出了对列表进行操作的小函数的示例,这在编写较大的程序时会很有帮助。
其中之一是flatten
。给定任意级别的嵌套列表作为参数,展平将删除所有嵌套元素并将它们放在顶层。
以下是我实现扁平化的尝试:
(defun flatten (lst)
(labels ((rflatten (lst1 acc)
(dolist (el lst1)
(if (listp el)
(rflatten el acc)
(push el acc)))
acc))
(reverse (rflatten lst nil))))
但上述函数没有正确展平列表。
; returns (1) instead of (1 2)
(print (flatten '(1 (2))))
(1)
调用该函数(1 (2))
回报(1)
代替(1 2)
.
我找不到我的扁平化实施有什么问题。这是我使用的方式吗labels
?或者是我使用的方式dolist
宏?这dolist
宏总是返回nil
。但这并不重要,因为我正在使用累加器acc
存储展平列表。
push
更改范围内的符号绑定。因此递归(rflatten el acc)
有它自己的acc
这是那里的结果,但您不对返回的结果执行任何操作,并且它不会改变被调用者acc
.
也许是一个(setf acc (rflatten el acc))
会解决这个问题:
(defun flatten (lst)
(labels ((rflatten (lst1 acc)
(dolist (el lst1)
(if (listp el)
(setf acc (rflatten el acc))
(push el acc)))
acc))
(reverse (rflatten lst nil))))
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)