0

我需要用 lisp 编写一个带有两个参数的函数 - 无参数函数列表和整数列表。我需要按照第二个给出的顺序评估第一个列表中的函数,即 (fun '(#'a #'b #'c) '(2 0 1)) 应该评估 c、a、b。我试过这样的功能:

(defun z4(funs kols)
    (funcall (nth (first kols) funs))
    (z4 funs (rest kols))
)

但在 funcall 我收到错误

NIL 不是 CONS 类型。

这是什么意思?我通过简单地调用得到同样的错误

(funcall (first funs))

所以我认为它与从函数列表中获取函数有关。如何评估从函数列表中获取的函数?

4

2 回答 2

5

每次递归调用都会减少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和 列表来提供随机访问的集合对性能不利,因此将函数存储在 a vector(即一维array)而不是列表中可能更值得。所以,假设funcs是一个vector函数,函数可以定义如下:

(defun foo (funcs order)
  (loop for n in order do (funcall (aref funcs n))))

此外,如果函数数组是(词汇表条目) ,我们可以aref替换为。前者更通用,但后者在某些实现中可能更快。svrefsimple vector

可以使用以下任一方法创建一个simple vector函数

(vector #'func-a #'func-b ...)

或者

#(func-a func-b ...)

A simple vectorof 函数也可以使用该make-array函数创建,但前提是:adjustable:fill-pointer关键字参数未指定 or nil

于 2013-01-26T13:35:20.327 回答
4
'(#'a #'b #'c)

不是函数 A、B、C 的列表。它是这样的:

((FUNCTION A) (FUNCTION B) (FUNCTION C))

上面不是函数,而是带有第一个符号FUNCTION然后是另一个符号的列表。

使用任一

(list #'a #'b #'c)

或者

'(a b c)
于 2013-01-26T14:15:39.743 回答