Pax*_*x0r 0 lisp functional-programming function list
我需要在lisp中编写一个带有两个参数的函数 - 无参数函数列表和整数列表.我需要按照第二个列表的顺序评估第一个列表中的函数,即(有趣的'(#'a#b#'c)'(2 0 1))应该评估c,a,b.我试过这样的功能:
(defun z4(funs kols)
(funcall (nth (first kols) funs))
(z4 funs (rest kols))
)
Run Code Online (Sandbox Code Playgroud)
但是在funcall我发现错误
NIL不属于CONS类型.
这是什么意思?通过简单地调用我得到同样的错误
(funcall (first funs))
Run Code Online (Sandbox Code Playgroud)
所以我认为它与从函数列表中获取函数有关.如何从函数列表中评估函数?
每次递归调用都会减少kols参数,直到变为参数nil.当kols成为nil你应终止递归,所以你应该添加测试的终止条件(即空列表):
(defun foo (funcs order)
(unless (endp order)
(funcall (nth (first order) funcs))
(foo funcs (rest order))))
Run Code Online (Sandbox Code Playgroud)
我建议一个更易读的解决方案(因为ANSI Common Lisp Standard不强制实现执行尾调用优化,所以它也更优选):
(defun foo (funcs order)
(loop for n in order do (funcall (nth n funcs))))
Run Code Online (Sandbox Code Playgroud)
在前面的示例中,我假设您为副作用运行函数,而不是返回值.
编辑1
正如Vatine所指出的那样,使用nth和列表来提供具有随机访问权限的集合对性能不利,因此将函数存储在vector(即一维array)rathen而不是列表中可能是值得的.因此,假设这funcs是一个vector函数,函数可以定义如下:
(defun foo (funcs order)
(loop for n in order do (funcall (aref funcs n))))
Run Code Online (Sandbox Code Playgroud)
此外,我们可以代替aref与svref如果功能的阵列是simple vector(词汇表条目).前者更为通用,但后者在某些实现中可能更快.
可以simple vector使用其中任何一个创建函数
(vector #'func-a #'func-b ...)
Run Code Online (Sandbox Code Playgroud)
要么
#(func-a func-b ...)
Run Code Online (Sandbox Code Playgroud)
甲simple vector的功能都可以通过创建make-array函数为好,但仅当:adjustable和:fill-pointer关键字参数未指定或nil.