h__
h__

Reputation: 873

how do I use a function as a variable in lisp?

I'm trying to write a function which checks if every element in the list x has property a, so I wrote:

(defun check (a x)
  (if (listp x)
    (eval (cons 'and (mapcar #'a x)))))

but it doesn't work. (Basically I want a to be the name of a function, say blablabla, and in the body of the check-function, by #'a I want to mean the function blablabla, instead of a function called a.) Now the code above doesn't work. I think in Lisp one should be able to plug in functions. How can I fix it?

(It is literally my first day on lisp, so it might be a stupid question ;) and BTW I'm using Lispworks 6.0 personal version.)

Upvotes: 3

Views: 546

Answers (3)

whoplisp
whoplisp

Reputation: 2518

Here is how I would write something like your check function. I tried to give it a more descriptive name.

(defun are-all-elements-fullfilling-fun-p (fun ls)
  (every #'identity (mapcar fun ls)))

Edit: Note that a shorter and better definition is

(defun are-all-elements-fullfilling-fun-p (fun ls)
      (every fun ls)))

Now let's say we want to call it with this function. Note that I tend to use declarations when possible. I quite often screw something up and debugging is easy if the compiler can figure the error out. Also the code will run faster.

(defun is-even-p (n)
  (declare (type number n))
  (the boolean (= 0 (mod n 2))))

You have to place the #' here:

(are-all-elements-fullfilling-fun-p #'is-even-p '(1 2 3 4))
(are-all-elements-fullfilling-fun-p #'is-even-p '(38 2 4))

Upvotes: 3

Michael Markert
Michael Markert

Reputation: 4026

You don't need eval you can use apply. To the problem: You need funcall because you provide a as argument. (Edit: Not in this case.) By quoting you just refer to the function a not the a in this function.

(defun check (a xs)
  (if (listp xs)
      (every #'identity (mapcar a
                                xs))))

Better, use loop:

(defun check (a xs)
  (if (listp xs)
      (loop for x in xs
            always (funcall a x))))

Best, use every:

(defun check (a xs)
   (if (listp xs)
     (every a xs)))

Upvotes: 3

Matthias Benkard
Matthias Benkard

Reputation: 15759

There is no need to use the sharp-quote syntax here. Its purpose is to use a function name in a variable position, but a is a variable already. Just write a instead of #'a.

Upvotes: 6

Related Questions