用于 mapcar 的 lambda 中的 Lisp 操作顺序

标签 lisp common-lisp

我正在 Linux 中运行 clisp,并进行书中的练习,ANSI Common Lisp。其中之一说使用 mapcar 创建一个函数,该函数接受一个整数列表并返回一个列表,其中每个元素都是原始元素加上它在列表中的索引。因此,如果我执行 (foo '(0 0 0)),它将生成 (0 1 2) 等。

我试过的是这样的:

(defun foo (lst)
  (let ((c 0))
    (mapcar #'(lambda (x) (+ x c) (incf c)) lst)))

当我运行 (foo '(0 0 0)) 时我得到的是 (1 2 3)。作为实验,我交换了增量的顺序并这样定义它:

(defun foo (lst)
  (let ((c 0))
    (mapcar #'(lambda (x) (incf c) (+ x c)) lst)))

我得到了完全相同的结果(在这种情况下,我希望 (1 2 3),但在前一种情况下不会)。我也尝试像这样包装序列 (progn (+ x c) (incf c)) 并得到相同的结果。为了使该功能正常工作,我需要执行 (let ((c -1)))。为什么 (incf c)(+ x c) 的顺序在这种情况下似乎无关紧要?看起来 (incf c) 无论如何总是先完成,但我不确定为什么。我知道我在这里遗漏了一些基本的东西,所以这应该是 LISP 专家的一个快速简单的回答,向我解释为什么这样工作。 :)

谢谢。

最佳答案

在您的第一个示例中,lambda 函数的结果是最后一种形式 (incf c) 的结果。 (+ x c) 被忽略。

在您的第二个示例中,您首先递增 c,因此第一个数字加 1,第二个数字加 2,依此类推。

对于您的第一个示例,您还可以使用 prog1 返回第一个 形式的值,而不是最后一个:

(defun foo (lst)
  (let ((c 0))
    (mapcar
     (lambda (e) (prog1 (+ e c) (incf c)))
     lst)))

关于用于 mapcar 的 lambda 中的 Lisp 操作顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20911878/

相关文章:

optimization - 查找质因数太慢或崩溃

sockets - 为什么我不能使用 usocket::socket-receive 从我的 usocket 读取数据?

lisp 读取命令对 sbcl 工作错误

lisp - 如何检查符号是否为 T?

lisp - 获取当前在 Steel Bank Common Lisp 中执行的脚本的路径

lambda - 使用函数中的 lambda 值作为列表的第一个元素

lisp - 从 cl-user 包导入

lisp - Lisp 中的快速排序奇怪的行为?

lisp - 转换多个对象的vlax-ename->vla-object

lisp - 如何在Lisp中的函数内全局更改变量值