简体   繁体   中英

Evaluate function from list in lisp

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, ie (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?

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 (ie, 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 .

'(#'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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM