我需要用 lisp 编写一个带有两个参数的函数——无参数函数列表和整数列表。 我需要按照第二个给定的顺序评估第一个列表中的函数,即 (fun '(#'a #'b #'c) '(2 0 1)) 应该评估 c、a、b。 我试过这样的功能:
(defun z4(funs kols)
(funcall (nth (first kols) funs))
(z4 funs (rest kols))
)
但是在函数调用中我得到了错误
NIL is not of type CONS.
这是什么意思?我通过简单地调用得到了同样的错误
(funcall (first funs))
所以我假设它与从函数列表中获取函数有关。如何评估从函数列表中获取的函数?
最佳答案
每次递归调用时,您都会减少 kols
参数,直到它变为 nil
。当 kols
变为 nil
时,您应该终止递归,因此您应该添加终止条件(即空列表)的测试:
(defun foo (funcs order)
(unless (endp order)
(funcall (nth (first order) funcs))
(foo funcs (rest order))))
我建议一个更具可读性的解决方案(它也更可取,因为 ANSI Common Lisp 标准不强制实现执行尾调用优化):
(defun foo (funcs order)
(loop for n in order do (funcall (nth n funcs))))
在前面的示例中,我假设您运行函数是为了它们的副作用,而不是为了返回值。
编辑 1
正如 Vatine 指出的那样,使用 nth
和列表来提供随机访问的集合对性能不利,因此将函数存储在 vector
中可能是值得的(这是一个一维数组
)而不是列表。因此,假设 funcs
是函数的 vector
,函数可以定义如下:
(defun foo (funcs order)
(loop for n in order do (funcall (aref funcs n))))
此外,如果函数数组是简单向量
( glossary entry ),我们可以将aref
替换为svref
。前者更通用,但后者在某些实现中可能更快。
可以使用任一方法创建函数的简单向量
(vector #'func-a #'func-b ...)
或
#(func-a func-b ...)
也可以使用 make-array
函数创建函数的简单向量
,但前提是 :adjustable
和 :fill-pointer
关键字参数未指定或 nil
。
关于list - 从 lisp 中的列表中评估函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14537372/