[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.lisp

Odd behavior with funcall

simiusmathematicus

11/7/2015 9:02:00 PM

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?

Thanks for any insight you can provide.

3 Answers

Pascal J. Bourguignon

11/7/2015 9:22:00 PM

0

simiusmathematicus@gmail.com writes:

> 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))
> |my-system|> (setf my-list '(foo 2 3))
> |my-system|> (funcall (first my-list) 3)
>
> I thought funcall had to act on a function object and not on a
> function name, so what am I missing here?

You're missing the semantics of CL:QUOTE.

http://www.lispworks.com/documentation/HyperSpec/Body/s_quote...

Also, it would be nice to declare your variables first!

(defvar *my-list*)
(setf *my-list* '(foo 2 3))


You may visualize your lists with draw-list. Compare the various data
structures obtained:

user1> (ql:quickload :com.informatimago.common-lisp)

user1> (com.informatimago.common-lisp.picture.cons-to-ascii:draw-list '(foo 2 3))
+-----------------------------------+
| (foo 2 3) |
| |
| +---+---+ +---+---+ +---+---+ |
| | * | * |-->| * | * |-->| * |NIL| |
| +---+---+ +---+---+ +---+---+ |
| | | | |
| v v v |
| +-----+ +---+ +---+ |
| | foo | | 2 | | 3 | |
| +-----+ +---+ +---+ |
+-----------------------------------+

user1> (com.informatimago.common-lisp.picture.cons-to-ascii:draw-list '((function foo) 2 3))
+-----------------------------------+
| (#'foo 2 3) |
| |
| +---+---+ +---+---+ +---+---+ |
| | * | * |-->| * | * |-->| * |NIL| |
| +---+---+ +---+---+ +---+---+ |
| | | | |
| | v v |
| | +---+ +---+ |
| | | 2 | | 3 | |
| | +---+ +---+ |
| v |
| +---+---+ +---+---+ |
| | * | * |-->| * |NIL| |
| +---+---+ +---+---+ |
| | | |
| v v |
| +----------++-----+ |
| | function || foo | |
| +----------++-----+ |
+-----------------------------------+

user1> (com.informatimago.common-lisp.picture.cons-to-ascii:draw-list (list 'foo 2 3))
+-----------------------------------+
| (foo 2 3) |
| |
| +---+---+ +---+---+ +---+---+ |
| | * | * |-->| * | * |-->| * |NIL| |
| +---+---+ +---+---+ +---+---+ |
| | | | |
| v v v |
| +-----+ +---+ +---+ |
| | foo | | 2 | | 3 | |
| +-----+ +---+ +---+ |
+-----------------------------------+

user1> (com.informatimago.common-lisp.picture.cons-to-ascii:draw-list (list (function foo) 2 3))
+---------------------------------------------+
| (#<compiled-function foo #x3020023e0cbf> 2 3)
| |
| +---+---+ +---+---+ +---+---+ |
| | * | * |-->| * | * |-->| * |NIL| |
| +---+---+ +---+---+ +---+---+ |
| | | | |
| | v v |
| | +---+ +---+ |
| | | 2 | | 3 | |
| | +---+ +---+ |
| v |
| +-----------------------------------------+ |
| | #<Compiled-function foo #x3020023E0CBF> | |
| +-----------------------------------------+ |
+---------------------------------------------+

--
__Pascal Bourguignon__ http://www.informat...
â??The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.� -- Carl Bass CEO Autodesk

Antsan

11/7/2015 10:34:00 PM

0

Am Samstag, 7. November 2015 22:01:52 UTC+1 schrieb simiusmat...@gmail.com:
> 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>.

The call
(funcall (first my-list) 3)
here is equivalent to
(funcall '(function foo) 3)
Note the quote! This is not the same as calling
(funcall (function foo) 3)
so you get an error because '(function foo) does not denote a function.

> 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 funcallable objects and if given a symbol it looks up its
function definition.
(funcall '+ 1 2)
is definitely valid Common Lisp.

So, your call
(funcall (first my-list) 3)
here is equivalent to
(funcall 'foo 3)
This is the same as
(funcall (function foo) 3)
because 'foo denotes the function object (function foo).

> Thanks for any insight you can provide.
I hope I could provide insight.

Kaz Kylheku

11/7/2015 11:47:00 PM

0

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))