In 这个非常有用的答案,建议我可以替换这段代码:
(defun describe-paths (location edges)
(apply (function append) (mapcar #'describe-path
(cdr (assoc location edges)))))
有了这个:
(defun describe-paths-mapcan (location edges)
(mapcan #'describe-path
(cdr (assoc location edges))))
我当然从概念上理解为什么这应该有效,但事实并非如此;第二种变体冻结了我的 REPL,并且 CL 提示永远不会返回。我必须重新启动 SLIME。所以我查了一下,我想知道 mapcan 是否不使用list
, 反而nconc
,是原因吗?因此,这些实际上不是功能相同的代码块?
为了好奇,我传递这个:
(describe-paths-mapcan 'living-room *edges*)
Where *edges*
is:
(defparameter *edges* '((living-room (garden west door)
(attic upstairs ladder))
(garden (living-room east door))
(attic (living-room downstairs ladder))))
And:
(defun describe-path (edge)
`(there is a ,(caddr edge) going ,(cadr edge) from here.))
我认为这与describe-edges
。它定义为:
(defun describe-path (edge)
`(there is a ,(caddr edge) going ,(cadr edge) from here.))
那里的准引用我们可以macroexpand
..你得到:
(macroexpand '`(there is a ,(caddr edge) going ,(cadr edge) from here.)) ; ==>
(CONS 'THERE
(CONS 'IS
(CONS 'A
(CONS (CADDR EDGE) (CONS 'GOING (CONS (CADR EDGE) '(FROM HERE.)))))))
根据Mapcan 的文档连接是破坏性的。查看返回的最后一个元素describe-path
将与其返回的下一个元素共享结构,因此nconc
将会无限循环。
如果你要改变describe-edges
以下它将起作用:
(defun describe-path (edge)
(list 'there 'is 'a (caddr edge) 'going (cadr edge) 'from 'here.))
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)