From: Jyri J. Virkki
Subject: simple funcall question
Date: 
Message-ID: <1226emv51rqpq3d@corp.supernews.com>
I've been playing with Lisp a bit to get a hang of the basics. In one
app I have a list of assorted items, some of which are functions that
may need to get called later. But I'm missing something in my syntax
to make it work.  I've reduced the question to:

  CL-USER> (funcall #'(lambda () (format t "called~%")))
  called
  NIL

Ok, and

  CL-USER> (nth 1 '("foo" #'(lambda () (format t "called~%"))))
  #'(LAMBDA () (FORMAT T "called~%"))

But combining these,

  CL-USER> (funcall (nth 1 '("foo" #'(lambda () (format t "called~%")))))
  ; Evaluation aborted

looks like it doesn't "see" the function as a function, confirmed by

  CL-USER> (functionp (nth 1 '("foo" #'(lambda () (format t "called~%")))))
  NIL

Why? And how to fix it?


Thanks..

-- 
Jyri J. Virkki - Santa Cruz, CA

From: Ken Tilton
Subject: Re: simple funcall question
Date: 
Message-ID: <vDHUf.309$De5.225@fe08.lga>
Jyri J. Virkki wrote:
> I've been playing with Lisp a bit to get a hang of the basics.

You skipped the basic known as QUOTE, aka '

That is not your fault. All introductory material messes noobs up by 
always using things like '(a b c) in their elementary examples. So noobs 
think that is how to make a list. Yeah, if you want everything quoted. 
Which is line only for most elementary examples. :)

Try: (funcall (nth 0 (list (lambda () (print "hi mom")))))

ken

>  In one
> app I have a list of assorted items, some of which are functions that
> may need to get called later. But I'm missing something in my syntax
> to make it work.  I've reduced the question to:
> 
>   CL-USER> (funcall #'(lambda () (format t "called~%")))
>   called
>   NIL
> 
> Ok, and
> 
>   CL-USER> (nth 1 '("foo" #'(lambda () (format t "called~%"))))
>   #'(LAMBDA () (FORMAT T "called~%"))
> 
> But combining these,
> 
>   CL-USER> (funcall (nth 1 '("foo" #'(lambda () (format t "called~%")))))
>   ; Evaluation aborted
> 
> looks like it doesn't "see" the function as a function, confirmed by
> 
>   CL-USER> (functionp (nth 1 '("foo" #'(lambda () (format t "called~%")))))
>   NIL
> 
> Why? And how to fix it?
> 
> 
> Thanks..
> 


-- 
Cells: http://common-lisp.net/project/cells/

"And I will know my song well before I start singing."  - Bob Dylan
From: Pascal Bourguignon
Subject: Re: simple funcall question
Date: 
Message-ID: <87odzwmzat.fsf@thalassa.informatimago.com>
·······@localhost.localdomain (Jyri J. Virkki) writes:

> I've been playing with Lisp a bit to get a hang of the basics. In one
> app I have a list of assorted items, some of which are functions that
> may need to get called later. But I'm missing something in my syntax
> to make it work.  I've reduced the question to:
>
>   CL-USER> (funcall #'(lambda () (format t "called~%")))
>   called
>   NIL
>
> Ok, and
>
>   CL-USER> (nth 1 '("foo" #'(lambda () (format t "called~%"))))
>   #'(LAMBDA () (FORMAT T "called~%"))
>
> But combining these,
>
>   CL-USER> (funcall (nth 1 '("foo" #'(lambda () (format t "called~%")))))
>   ; Evaluation aborted
>
> looks like it doesn't "see" the function as a function, confirmed by
>
>   CL-USER> (functionp (nth 1 '("foo" #'(lambda () (format t "called~%")))))
>   NIL
>
> Why? And how to fix it?


First, you should note that 'x is just a shorthand for (quote x)
                       and #'x is just a shorthand for (function x)
there's nothing special about them.

Next, you should know that most Common Lisp implementations lie to you:

[3]> (print '(function x))

#'X 
#'X
[4]> (asdf-load :com.informatimago.common-lisp)
[...]
[5]> (com.informatimago.common-lisp.cons-to-ascii:print-conses '(function x))
(FUNCTION  . (X  . ()))
#'X

Compare with:

[6]> (print '(fonction x))

(FONCTION X) 
(FONCTION X)
[7]> (com.informatimago.common-lisp.cons-to-ascii:print-conses '(fonction x))
(FONCTION  . (X  . ()))
(FONCTION X)
[8]> 


As you can see, a mere list, no different from any other list, instead
of being printed as its elements inside parentheses like any other
list, is printed as #'x just because its first element is CL:FUNCTION
and it contains only two element.  I find this special casing
unjustifiable, but I'm no lisp implementer (yet).


Now, check out your second result. It prints as :
    #'(LAMBDA () (FORMAT T "called~%"))
and if you read it back, it would be read as a function.  
But it isn't a function!  It's a plain list:

[8]> (com.informatimago.common-lisp.cons-to-ascii:print-conses 
        (nth 1 '("foo" #'(lambda () (format t "called~%")))))
(FUNCTION  . ((LAMBDA  . (() . ((FORMAT  . (T  . (called~%  . ()))) . ()))) . ()))
#'(LAMBDA NIL (FORMAT T "called~%"))
[9]> (car (nth 1 '("foo" #'(lambda () (format t "called~%")))))
FUNCTION
[10]> (type-of (nth 1 '("foo" #'(lambda () (format t "called~%")))))
CONS
[11]> 



The reason why, may be clearer if you avoided ' and #' and wrote QUOTE
and FUNCTION instead:

  (nth 1 (QUOTE ("foo" (FUNCTION (lambda () (format t "called~%"))))))

What does this conspicuous QUOTE do here?

Yes, it prevents the evaluation of its argument and returns it as is.
Therefore you get the second element of the list:
     ("foo" (FUNCTION (lambda () (format t "called~%"))))
which is itself the list:
     (FUNCTION (lambda () (format t "called~%")))
There's no function here!





Note that functions cannot be read.  When you print a function, it's
printed with #< which is a reader dispatching macro for unreadable
stuff:

[11]> (print (function sin))

#<SYSTEM-FUNCTION SIN> 
#<SYSTEM-FUNCTION SIN>
[12]> (print (lambda (x y) (+ (* 2 x) y)))

#<FUNCTION :LAMBDA (X Y) (+ (* 2 X) Y)> 
#<FUNCTION :LAMBDA (X Y) (+ (* 2 X) Y)>
[13]>  #<FUNCTION :LAMBDA (X Y) (+ (* 2 X) Y)> 

*** - READ from
       #<INPUT CONCATENATED-STREAM #<INPUT STRING-INPUT-STREAM>
         #<IO TERMINAL-STREAM>>
      : objects printed as #<...> cannot be read back in



Therefore, to input a function you need to actually _evaluate_ an
expression that will find or build it.


(FUNCTION SIN) is such an expression.  
When evaluated, it finds the function named SIN and returns it.


(FUNCTION (lambda () (format t "called~%")))  is another such expression.
When evaluated, it builds an anonymous function that formats "called~%" 
and returns it.


(LAMBDA () (format t "called~%"))  is such an expression too!

Indeed, when this form is evaluated, since LAMBDA is a macro that
expands (lambda args . body)  to (function (lambda args . body)),
it results in another anonymous function all the same.



So what you need to get functions is have the expressions that build
or find them be evaluated.  Therefore you must avoid QUOTE.  You can
use LIST to build lists, after evaluating the elements:


[15]> (list (quote "foo") (lambda () (format t "called~%")) (function sin))

("foo" #<FUNCTION :LAMBDA NIL (FORMAT T "called~%")> #<SYSTEM-FUNCTION SIN>)

[16]> (funcall (second (list (quote "foo") (lambda () (format t "called~%")) (function sin))))
called
NIL


Another way to build such a list, when it contains a lot of data that
shouldn't be evaluated and a few that should:

(list (quote a) (quote b) (quote 1) (function car) (quote 3) (quote "hi"))

is to use the backquote and comma reader macros:

    `(a b 1 ,(function car) 3 "hi")

reading this backquote expression, the reader builds an expressions
that will give a result simular to the list expression above.

[20]> (funcall (second `("foo" ,(lambda () (format t "called~%")) ,(function sin))))
called
NIL



[Unfortunately, there is no standard expansion for backquote and
 comma. Well their purpose  is to have a short and convenient notation
 to write these lists, so nobody would write: 
   (backquote a b 1 (comma (function car)) 3 "hI") 
 anyways.]



[You may have been surprised by my (quote "foo") above ;-) There's a
 difference between "foo" and (quote "foo"), but when you evaluate
 them, you have in the first case a self-evaluating atom, where
 evaluating "foo" results in "foo" itself, and in the second case,
 QUOTE returns its argument "foo" unevaluated, as is, "foo" itself.
 The result of evaluating (quote "foo") or "foo" is the same!  (But
 when things are not evaluated, then (quote "foo") is a list while
 "foo" is a string, not the same).]

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
In deep sleep hear sound,
Cat vomit hairball somewhere.
Will find in morning.
From: Harald Hanche-Olsen
Subject: Re: simple funcall question
Date: 
Message-ID: <pcok6akgvw1.fsf@shuttle.math.ntnu.no>
+ Pascal Bourguignon <······@informatimago.com>:

| First, you should note that 'x is just a shorthand for (quote x)
|                        and #'x is just a shorthand for (function x)
| there's nothing special about them.

You mean, apart from them being special forms?  ;->

(Yeah, I know what you're saying - if they don't even get to be
 evaulated, they're just plain lists ...)

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- It is undesirable to believe a proposition
  when there is no ground whatsoever for supposing it is true.
  -- Bertrand Russell
From: Mikko Heikelä
Subject: Re: simple funcall question
Date: 
Message-ID: <Pine.OSF.4.61.0603240227410.54314@kosh.hut.fi>
On Fri, 24 Mar 2006, Jyri J. Virkki wrote:
>  CL-USER> (nth 1 '("foo" #'(lambda () (format t "called~%"))))
>  #'(LAMBDA () (FORMAT T "called~%"))

Here, you make a sensible attempt to understand the problem, but you 
are fooled by the printer, which uses the same shortcut notations that 
are available for you in the reader.  #'something is equivalent to 
(function something).

> But combining these,
>
>  CL-USER> (funcall (nth 1 '("foo" #'(lambda () (format t "called~%")))))
>  ; Evaluation aborted
>
> looks like it doesn't "see" the function as a function, confirmed by
>
>  CL-USER> (functionp (nth 1 '("foo" #'(lambda () (format t "called~%")))))
>  NIL
>
> Why? And how to fix it?

Trying:
(type-of (nth 1 '("foo" #'(lambda () (format t "called~%")))))
might lead you to the right direction.

The problem is that the quote in '("foo" ... ) suppresses evaluation 
of everything in ... .  Therefore the form

(function (lambda () (format t "called~%")))

is not evaluated into the actual function, but remains just a sublist 
in your list.  In general you will want to use the function list to 
construct lists, as opposed to the quote operator, which always 
produces constant lists.

  -Mikko
From: Frode Vatvedt Fjeld
Subject: Re: simple funcall question
Date: 
Message-ID: <2hpskcni4h.fsf@vserver.cs.uit.no>
·······@localhost.localdomain (Jyri J. Virkki) writes:

>   CL-USER> (funcall #'(lambda () (format t "called~%")))
>   CL-USER> (funcall (nth 1 '("foo" #'(lambda () (format t "called~%")))))
>   ; Evaluation aborted
> Why?

Try to replace funcall with print, and compare the results.

-- 
Frode Vatvedt Fjeld
From: Pascal Bourguignon
Subject: Re: simple funcall question
Date: 
Message-ID: <87fyl7n6b7.fsf@thalassa.informatimago.com>
Frode Vatvedt Fjeld <······@cs.uit.no> writes:
> ·······@localhost.localdomain (Jyri J. Virkki) writes:
>
>>   CL-USER> (funcall #'(lambda () (format t "called~%")))
>>   CL-USER> (funcall (nth 1 '("foo" #'(lambda () (format t "called~%")))))
>>   ; Evaluation aborted
>> Why?
>
> Try to replace funcall with print, and compare the results.

This is confusing because implementers choose to print the shortcut
in most cases.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

The world will now reboot.  don't bother saving your artefacts.
From: Christophe Rhodes
Subject: Re: simple funcall question
Date: 
Message-ID: <sqveu37o82.fsf@cam.ac.uk>
Pascal Bourguignon <······@informatimago.com> writes:

> Frode Vatvedt Fjeld <······@cs.uit.no> writes:
>> ·······@localhost.localdomain (Jyri J. Virkki) writes:
>>
>>>   CL-USER> (funcall #'(lambda () (format t "called~%")))
>>>   CL-USER> (funcall (nth 1 '("foo" #'(lambda () (format t "called~%")))))
>>>   ; Evaluation aborted
>>> Why?
>>
>> Try to replace funcall with print, and compare the results.
>
> This is confusing because implementers choose to print the shortcut
> in most cases.

It is not confusing, because one print command will print
  #<FUNCTION (LAMBDA NIL)> ; or similar
and the other will print
  #'(LAMBDA () (FORMAT T "called~%"))
which is sufficiently different that an alarm bell could ring.

I don't think that there would be any extra clarity in this case if
the second printed thing were
  (FUNCTION (LAMBDA () (FORMAT T "called~%")))

Christophe