我正在 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/