Kaz Kylheku
11/7/2015 11:47:00 PM
On 2015-11-07, simiusmathematicus@gmail.com <simiusmathematicus@gmail.com> wrote:
> Hello,
>
> I'm relatively new to Common Lisp, so this might be obvious to experienced users but is certainly not obvious to me.
>
> In the CL REPL I've entered the following and get an error
>
>|my-system|> (defun foo (x) (* x x))
> WARNING: redefining |my-system|::FOO in DEFUN
> FOO
>|my-system|> (setf my-list '((function foo) 2 3))
>
> ; in: SETF MY-LIST
> ; (SETF |my-system|::MY-LIST '(#'|my-system|::FOO 2 3))
> ; ==>
> ; (SETQ |my-system|::MY-LIST '(#'|my-system|::FOO 2 3))
> ;
> ; caught WARNING:
> ; undefined variable: MY-LIST
> ;
> ; compilation unit finished
> ; Undefined variable:
> ; MY-LIST
> ; caught 1 WARNING condition
> (#'FOO 2 3)
>|my-system|> (funcall (first my-list) 3)
> ; Evaluation aborted on #<TYPE-ERROR expected-type: (OR FUNCTION SYMBOL) datum: #'|my-system|::FOO>.
>
> However, if I change my-list to:
>
>
>|my-system|> (setf my-list '(foo 2 3))
>
> ; (SETF |my-system|::MY-LIST '(|my-system|::FOO 2 3))
> ; ==>
> ; (SETQ |my-system|::MY-LIST '(|my-system|::FOO 2 3))
> ;
> ; caught WARNING:
> ; undefined variable: MY-LIST
> ;
> ; compilation unit finished
> ; Undefined variable:
> ; MY-LIST
> ; caught 1 WARNING condition
> (FOO 2 3)
>|my-system|> (funcall (first my-list) 3)
> 9
>
> I don't get an error.
>
> I thought funcall had to act on a function object and not on a function name,
> so what am I missing here?
Funcall acts on a function object or a symbol which has a function binding
in the given lexical or global environment.
This is why (funcall (first my-list) 3) works when my-list holds
the object (foo 2 3). (first my-list) produces the symbol foo, which
has a function binding.
The funcall doesn't work when my-list holds ((function foo) 2 3)
because (first my-list) is (function foo), a list of two elements.
funcall doesn't take such a thing.
Of coruse (function foo) is an expression; if it is evaluated as a form,
its *value* is a function object, and funcall takes that:
(funcall (eval (first my-list)) 3)
Or even:
(eval `(funcall ,(first my-list) 3))
It's usually best to think of a way to avoid eval. Like, for instance,
to prepare the list so that it contains a function object in the
first place, for instance with backquote:
(setf my-list `(,(function foo) 2 3))
Or without backquote:
(setf my-list (list (function foo) 2 3))