Reputation: 2473
I need to write a function in lisp with two arguments - list of argumentless functions and list of integers. I need to evaluate functions from first list in order given by a second, i.e. (fun '(#'a #'b #'c) '(2 0 1)) should evaluate c, a, b. I tried such function:
(defun z4(funs kols)
(funcall (nth (first kols) funs))
(z4 funs (rest kols))
)
but in funcall I am geting error
NIL is not of type CONS.
What does it means? I am getting same error by calling simply
(funcall (first funs))
so I assume it is something with with getting function from the list of functions. How can I evaluate function get from list of functions?
Upvotes: 0
Views: 1979
Reputation: 1979
With each recursive call you reduce the kols
parameter untill it becomes nil
. When kols
becomes nil
you should terminate the recursion, so you should add the test for the terminating condition (i.e., for empty list):
(defun foo (funcs order)
(unless (endp order)
(funcall (nth (first order) funcs))
(foo funcs (rest order))))
I suggest a more readable solution (it's also more preferrable since ANSI Common Lisp Standard doesn't force implementations to perform tail call optimization):
(defun foo (funcs order)
(loop for n in order do (funcall (nth n funcs))))
In the previous examples I assume that you run your functions for their side effects, not for the return values.
Edit 1
As Vatine noted, using nth
and lists to provide a collection with random access is not good for the performance, so it might be worth to store functions in a vector
(that is a one-dimensional array
) rathen than in a list. So, assuming that funcs
is a vector
of functions, the function can be defined as follows:
(defun foo (funcs order)
(loop for n in order do (funcall (aref funcs n))))
Moreover, we can replace aref
with svref
if the array of functions is a simple vector
(glossary entry). The former is more general, but the latter may be faster in some implementations.
One can create a simple vector
of functions using either
(vector #'func-a #'func-b ...)
or
#(func-a func-b ...)
A simple vector
of functions can be created using the make-array
function as well, but only if :adjustable
and :fill-pointer
keyword arguments are unspecified or nil
.
Upvotes: 5
Reputation: 139401
'(#'a #'b #'c)
is not a list of functions A, B, C. It is this:
((FUNCTION A) (FUNCTION B) (FUNCTION C))
Above are not functions, but lists with the first symbol FUNCTION
and then another symbol.
Use either
(list #'a #'b #'c)
or
'(a b c)
Upvotes: 4