common-lisp - 忽略结果时,MAPCAR、MAPC 和 MAP 是否编译为类似的代码?

标签 common-lisp sbcl

第一个问题:假设 Common Lisp 的现代编译器通常会将 (mapcar #'fn ...)(map 'list #'fn ...) 编译成与 (mapc #'fn ...) 相同的代码是否合理?也就是说,假设编译器会看到返回值被忽略,因此不需要构造新列表是否合理?例如假设我的源文件包含以下代码:

(defun set-foo-5 (sym)
  (setf (get sym 'foo) 5))

(progn 
  (mapcar #'set-foo-5 '(a b c))
  (format t "All foos are five!~%"))
mapc 会更有效吗?我通常运行 SBCL,但我的猜测是任何好的编译器都能够弄清楚在这种情况下没有必要创建一个新列表。我对吗?

第二个问题:在相同的情况下,我是否应该假设现代编译器通常会将 map 'list 编译为与 mapcar 相同的代码,只要源代码中存在 'list 并且在运行时未选择?

第三个问题:其他序列的类似问题。例如,如果我用 mapcar 替换上面 progn 中的 (map 'vector #'set-foo-5 #(a b c)) 行,我是否应该假设编译后的代码不会费心构造一个新的向量?

最佳答案

首先是 map mapcar 有一个非常重要的区别:后者作用于 lists 而前者作用于任何 sequences 。这意味着只有当编译器可以证明所有数据参数都是 (map nil ...) 时,(map 'list ...)(或 (mapc ...))才等价于 (mapcar ...)(resp. list)。

其次 ,大多数现代 Lisp 编译器(例如 SBCL )通常足以解决这些问题(必要时带有声明)。

第三个 ,唯一可以确定的方法是使用 disassemble

第四个 ,函数选择是一种记录代码的方式。当您使用 map 时,您是在告诉代码的人类读者您将向函数传递非列表。如果您确定只使用列表,您为什么要混淆读者(几个月后的您自己)?

第五个 premature optimization is the root of all evil

关于common-lisp - 忽略结果时,MAPCAR、MAPC 和 MAP 是否编译为类似的代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19071338/

相关文章:

javascript - Parenscript 和隐式 Return

lisp - 抑制编译器错误

couchdb - Ironclad 和 couch pbkdf2 哈希之间不匹配

lisp - 1-和1+的历史

opengl - MacOS 上 SLIME 下的 cl-opengl 使 SBCL 崩溃...错误?

common-lisp - CFFI-UNIX 发生了什么?

lisp - Common Lisp 中的矩阵乘法

linux - Lisp 工具包 (ltk) : Cannot get SCALE :variable value

macros - SBCL 中奇怪的宏展开错误

common-lisp - Lisp SBCL 将函数参数声明为某种类型的列表,以进行类型检查