johnbakers
johnbakers

Reputation: 24750

Why doesn't this quoted form evaluate as expected

I have a simple function that works:

(defun ifelse (the-test)
  (cond (the-test (format t "passed test, true!"))
    (t (format t "failed test, boo hoo"))))

If I do this, I get what you'd expect:

(ifelse  (funcall (lambda () nil)))
failed test, boo hoo
NIL

I'm curious why this doesn't also result in a "failure" :

CL-USER> (ifelse  '(funcall (lambda () nil)))
passed test, true!
NIL

My thinking is that, rather than evaluating the funcall in place and then passing the return value into ifelse, the entire funcall is being passed unevaluated into the ifelse -- however, how is a quoted form treated within the function? Wouldn't it be essentially copied in-place and then treated as a true Lisp form?

Upvotes: 0

Views: 79

Answers (2)

fazerty
fazerty

Reputation: 410

In the example , you pass a list as argument (because of the quote). You need to use eval to evaluate the quoted list to have the 'failure'. like this

(ifelse  (eval '(funcall (lambda () nil))))

or remove the quote

(ifelse  (funcall (lambda () nil)))

Upvotes: 0

zck
zck

Reputation: 2762

Let's see what you actually get:

(defun return-argument (element) element)

[9]> (defun return-argument (element) element)
RETURN-ARGUMENT
[10]> (return-argument (funcall (lambda () nil)))
NIL

Ok, this is as expected. Now your second function call, which results in a failure.

[11]> (return-argument '(funcall (lambda () nil)))
(FUNCALL (LAMBDA NIL NIL))

Aha, this gives us a clue. We're not evaluating argument, because it's quoted. In fact, we can see we're getting it back as a list:

[19]> (listp (return-argument '(funcall (lambda () nil))))
T

Remember, when you quote something, you prevent it from being evaluated.

Note: return-argument is the same function as the built-in identity. I wrote a new one so you could see what it's doing under the hood.

Upvotes: 4

Related Questions