【问题标题】:Why does this mapcan cause my REPL to freeze?为什么这张地图会导致我的 REPL 冻结?
【发布时间】:2013-12-11 00:05:17
【问题描述】:

this very useful answer,有人建议我可以替换这段代码:

(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。所以我looked it up,我想知道mapcan 不使用list,而是使用nconc,是否是原因?因此这些实际上不是功能相同的代码块?

为了好奇,我通过这个:

(describe-paths-mapcan 'living-room *edges*)

*edges* 在哪里:

(defparameter *edges* '((living-room (garden west door)
             (attic upstairs ladder))
            (garden (living-room east door))
            (attic (living-room downstairs ladder))))

还有:

(defun describe-path (edge)
  `(there is a ,(caddr edge) going ,(cadr edge) from here.))

【问题讨论】:

  • 这是来自Lisp之国吗?
  • @DaoWen 最初,但我正在尝试用其他方法来编写那本书中的示例,这样我可以更好地学习语言

标签: lisp common-lisp


【解决方案1】:

我认为这与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.)))))))

根据documentation for mapcan,连接是破坏性的。查看从describe-path 返回的最后一个元素将与它返回的下一个元素共享结构,因此nconc 将形成无限循环。

如果您要将 describe-edges 更改为以下内容,它将起作用:

(defun describe-path (edge)
  (list 'there 'is 'a (caddr edge) 'going (cadr edge) 'from 'here.))

【讨论】:

  • 这表明准引用功能实际上是一个宏,我不知道;因此,这是一个如何设计宏以防止其他功能正确使用它的示例
  • 好收获!当然,反引号扩展器也可以将其翻译为(list 'from 'here.);以及引用列表如何表现 w.r.t.破坏性更新是undefined,所以这真的取决于实现。
  • @WillNess 用于可移植代码,那么避免使用反引号并始终使用 list 是否有意义?至少这样所有行为都是完全定义和可预测的
  • @OpenLearner 是的,要么这样,要么将反引号形式包含在 copy-list 调用中。
  • @OpenLearner 本着LOL 的精神,我会避免在参数上修改函数,因为这些函数被设计为功能性的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-23
  • 1970-01-01
  • 1970-01-01
  • 2017-08-18
  • 1970-01-01
  • 2016-01-24
  • 1970-01-01
相关资源
最近更新 更多