From: Andrei Stebkov
Subject: Passing function as a parameter in CMUCL
Date: 
Message-ID: <4171796d@news.nnrp.ca>
Hi,

Watching the video lecture of "Structure and Interpretation of Computer
Program" I decided to reproduce the algorithm of finding a square root in
my CMUCL environment.

That's what I defined (trying to follow as close as possible the lecturer):

(defun fixed-point (f start)
  (setq tolerance 0.0001)
  (defun close-enuf? (u v)
    (< (abs (- u v))
       tolerance))
  (defun iter (old new)
      (if (close-enuf? old new)
   new
   (iter new (f new))))
  (iter start (f start)))

(defun avg (a b)
  (/ (+ a b) 2.0))

(defun sqrt-1 (x)
  (fixed-point 
   (lambda (y)(avg (/ x y) y))
   1))

(sqrt-1 2)

Having evaluated all the defines in sequence I got the error:

Error in KERNEL::UNDEFINED-SYMBOL-ERROR-HANDLER:  the function F is
undefined.
   [Condition of type UNDEFINED-FUNCTION]

Maybe I shouldn't have typed the whole algorithm as the bottomline here is
passing function as an argument.
Is it that the Common Lisp implementation different from Scheme?
How is it possible to pass functions as arguments in CL?
Forgive me if my question is too newbie as I am a newbie :)

Thanks,
Andrei

From: Paul F. Dietz
Subject: Re: Passing function as a parameter in CMUCL
Date: 
Message-ID: <f92dnVCoqY_e4-zcRVn-oQ@dls.net>
Andrei Stebkov wrote:

> Having evaluated all the defines in sequence I got the error:
> 
> Error in KERNEL::UNDEFINED-SYMBOL-ERROR-HANDLER:  the function F is
> undefined.
>    [Condition of type UNDEFINED-FUNCTION]

You need to do (funcall f new) and (funcall f start) in place
of (f new) and (f start).  Common Lisp is not a Lisp-1 like Scheme;
functions are in a separate name space from variables.

	Paul
From: Andrei Stebkov
Subject: Re: Passing function as a parameter in CMUCL
Date: 
Message-ID: <41718e83@news.nnrp.ca>
Thanks to all who answered! To me this particular feature of Scheme looks
cleaner than CL's.

My next question would be is it possible to give a function a different name
without defining it.
Let's say instead of (+ 1 2 3) I'd type (plus 1 2 3).
I thought of macros but can't come up with a solution.
A function that returns a "pointer" to a function?
Sure I could go:

(setq plus '+)
(funcall plus 1 2 3)

But that would make an additional funcall keyword in the call.

Thanks!
Andrei


Andrei Stebkov wrote:

> Hi,
> 
> Watching the video lecture of "Structure and Interpretation of Computer
> Program" I decided to reproduce the algorithm of finding a square root in
> my CMUCL environment.
> 
> That's what I defined (trying to follow as close as possible the
> lecturer):
> 
> (defun fixed-point (f start)
>   (setq tolerance 0.0001)
>   (defun close-enuf? (u v)
>     (< (abs (- u v))
>        tolerance))
>   (defun iter (old new)
>       (if (close-enuf? old new)
>    new
>    (iter new (f new))))
>   (iter start (f start)))
> 
> (defun avg (a b)
>   (/ (+ a b) 2.0))
> 
> (defun sqrt-1 (x)
>   (fixed-point
>    (lambda (y)(avg (/ x y) y))
>    1))
> 
> (sqrt-1 2)
> 
> Having evaluated all the defines in sequence I got the error:
> 
> Error in KERNEL::UNDEFINED-SYMBOL-ERROR-HANDLER:  the function F is
> undefined.
>    [Condition of type UNDEFINED-FUNCTION]
> 
> Maybe I shouldn't have typed the whole algorithm as the bottomline here is
> passing function as an argument.
> Is it that the Common Lisp implementation different from Scheme?
> How is it possible to pass functions as arguments in CL?
> Forgive me if my question is too newbie as I am a newbie :)
> 
> Thanks,
> Andrei
From: Paul F. Dietz
Subject: Re: Passing function as a parameter in CMUCL
Date: 
Message-ID: <GIKdnfAH4aEZAuzcRVn-tA@dls.net>
Andrei Stebkov wrote:

> Thanks to all who answered! To me this particular feature of Scheme looks
> cleaner than CL's.

Until you write code that has a variable named 'list', or 'car', or...
You understand now where all those 'lst' variables come from in Scheme
examples, yes?

CL optimizes programmer mental effort in the common case (binding local
variables) at the expense of a slight increase in verbosity in the less
common case (calling a function value).

	Paul
From: David Sletten
Subject: Re: Passing function as a parameter in CMUCL
Date: 
Message-ID: <RXhcd.13106$Kl3.11400@twister.socal.rr.com>
Andrei Stebkov wrote:


> Let's say instead of (+ 1 2 3) I'd type (plus 1 2 3).
> I thought of macros but can't come up with a solution.
> A function that returns a "pointer" to a function?
> Sure I could go:
> 
> (setq plus '+)
> (funcall plus 1 2 3)
> 
> But that would make an additional funcall keyword in the call.

Make sure you understand the differences among the following:
1. (setq plus +) => The value of PLUS is the value of the variable +, 
namely the last form given to REPL 
(http://www.lispworks.com/reference/HyperSpec/Body/v_pl_plp.htm)
2. (setq plus '+) => The value of PLUS is the symbol +
3. (setq plus #'+) => The value of PLUS is the function associated with +

In the second and third case, FUNCALL works with either '+ or #'+, but 
the results may be different if you have a local function definition:
(flet ((+ (l) (length l)))
   (let ((plus1 '+)
         (plus2 #'+))
     (format t "~A~%" (funcall plus1 1 2))
     (format t "~A~%" (funcall plus2 '(1 2)))))


David Sletten
From: Pascal Bourguignon
Subject: Re: Passing function as a parameter in CMUCL
Date: 
Message-ID: <873c0e8cfr.fsf@thalassa.informatimago.com>
David Sletten <·····@slytobias.com> writes:
> Make sure you understand the differences among the following:
> 1. (setq plus +) => The value of PLUS is the value of the variable +,
> namely the last form given to REPL
> (http://www.lispworks.com/reference/HyperSpec/Body/v_pl_plp.htm)
> 2. (setq plus '+) => The value of PLUS is the symbol +
> 3. (setq plus #'+) => The value of PLUS is the function associated with +

You can do without the comments if you write them as:
2. (setq plus (quote +))
3. (setq plus (function +))

Which is actually what's seen by the lisp system:
(print '(setq plus #'+)) ==> (setq plus (function +))


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

Voting Democrat or Republican is like choosing a cabin in the Titanic.
From: Peter Seibel
Subject: Re: Passing function as a parameter in CMUCL
Date: 
Message-ID: <m3acumfcw2.fsf@javamonkey.com>
Pascal Bourguignon <····@mouse-potato.com> writes:

> David Sletten <·····@slytobias.com> writes:
>> Make sure you understand the differences among the following:
>> 1. (setq plus +) => The value of PLUS is the value of the variable +,
>> namely the last form given to REPL
>> (http://www.lispworks.com/reference/HyperSpec/Body/v_pl_plp.htm)
>> 2. (setq plus '+) => The value of PLUS is the symbol +
>> 3. (setq plus #'+) => The value of PLUS is the function associated with +
>
> You can do without the comments if you write them as:
> 2. (setq plus (quote +))
> 3. (setq plus (function +))
>
> Which is actually what's seen by the lisp system:
> (print '(setq plus #'+)) ==> (setq plus (function +))

Better make sure you bind *print-pretty* to NIL or the printer might
translate it back to #'+.

  CL-USER> (print '(setq plus #'+))

  (SETQ PLUS #'+) 
  (SETQ PLUS #'+)
  CL-USER> (write '(setq plus #'+) :pretty nil)
  (SETQ PLUS (FUNCTION +))
  (SETQ PLUS #'+)

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Christophe Turle
Subject: Re: Passing function as a parameter in CMUCL
Date: 
Message-ID: <4171964c$0$25710$636a15ce@news.free.fr>
"Andrei Stebkov" <········@tht.net> a �crit dans le message de
·············@news.nnrp.ca...
> Thanks to all who answered! To me this particular feature of Scheme looks
> cleaner than CL's.
>
> My next question would be is it possible to give a function a different
name
> without defining it.
> Let's say instead of (+ 1 2 3) I'd type (plus 1 2 3).

at least 3 solutions :

macro : (defmacro plus (&rest args) `(+ ,@args))
no overhead.

function : (defun plus (&rest args) (apply #'+ args))
usable as function argument ( ex: mapcar ).

hack : (setf (symbol-function 'plus) #'+)
no overhead, usable as fct argument.


___________________________________________________________
Christophe Turle.
(format nil ···@~S.~S" 'c.turle 'wanadoo 'fr)

sava preview : http://perso.wanadoo.fr/turle/lisp/sava.html
From: Pascal Costanza
Subject: Re: Passing function as a parameter in CMUCL
Date: 
Message-ID: <ckuaq5$4hk$1@newsreader2.netcologne.de>
Christophe Turle wrote:

> at least 3 solutions :
> 
> macro : (defmacro plus (&rest args) `(+ ,@args))
> no overhead.
> 
> function : (defun plus (&rest args) (apply #'+ args))
> usable as function argument ( ex: mapcar ).
> 
> hack : (setf (symbol-function 'plus) #'+)
> no overhead, usable as fct argument.

The possible overhead of the function solution comes from the fact that 
plus is possibly not inlined and the &rest args must be stored into a 
heap-allocated list in the general case because the compiler doesn't 
know whether you are going to need them outside of the control flow of 
the function call.

Those overheads can be avoided by the inline and dynamic-extent 
declarations respectively (unless the CL implementation doesn't 
recognize them - but I think most of them do).


Pascal

-- 
Tyler: "How's that working out for you?"
Jack: "Great."
Tyler: "Keep it up, then."
From: Pascal Costanza
Subject: Re: Passing function as a parameter in CMUCL
Date: 
Message-ID: <ckuai6$44e$1@newsreader2.netcologne.de>
Andrei Stebkov wrote:
> Thanks to all who answered! To me this particular feature of Scheme looks
> cleaner than CL's.

It may look cleaner, but it's actually just different.

> My next question would be is it possible to give a function a different name
> without defining it.
> Let's say instead of (+ 1 2 3) I'd type (plus 1 2 3).

(setf (symbol-function 'plus)
       (symbol-function '+))

...doesn't work for local functions though. The following works both for 
global and local functions:

(defun plus (&rest args)
   (declare (dynamic-extent args))
   (apply #'+ args))

(declaim (inline plus))


(flet ((plus (&rest args)
          (declare (dynamic-extent args))
          (apply #'+ args))) ; #'+ may be another local function!
   (declare (inline plus))
   ...)


A macro isn't necessary in this case, and inlined functions can still be 
passed around as first-class objects.


Pascal

-- 
Tyler: "How's that working out for you?"
Jack: "Great."
Tyler: "Keep it up, then."
From: Dirk Gerrits
Subject: Re: Passing function as a parameter in CMUCL
Date: 
Message-ID: <873c0d14lo.fsf@dirkgerrits.com>
Pascal Costanza <········@web.de> writes:

> (defun plus (&rest args)
>   (declare (dynamic-extent args))
>   (apply #'+ args))
>
> (declaim (inline plus))
>
[...]
>
> A macro isn't necessary in this case, and inlined functions can still be 
> passed around as first-class objects.

I thought you had to write the inline declamation before the function
definition?

Anyway, I completely agree with your suggestion.  Heck, even as a C++
programmer I knew not to use macros when inline functions would do. :)
(Of course, those macros were downright evil compared with Lisp
macros...)

Kind regards,

Dirk Gerrits
From: Fred Gilham
Subject: Re: Passing function as a parameter in CMUCL
Date: 
Message-ID: <u7is9a5d52.fsf@snapdragon.csl.sri.com>
One point nobody mentioned so far.  Lisp doesn't locally scope
defuns.  So you should write your program as follows:


(defun fixed-point (f start)
  (let ((tolerance .0001))
    (labels ((close-enuf? (u v)
	       (< (abs (- u v))
		  tolerance))
	     (iter (old new)
	       (if (close-enuf? old new)
		 new
		 (iter new (funcall f new)))))
      (iter start (funcall f start)))))


(defun avg (a b)
  (/ (+ a b) 2.0))

(defun sqrt-1 (x)
  (fixed-point
   (lambda (y)
     (avg (/ x y) y))
   1))


Otherwise it's as if you just put the functions close-enuf? and iter
at the top level.

-- 
Fred Gilham                                          ······@csl.sri.com
99% of lawyers give the rest a bad name.                -- Steve Wright
From: Jochen Schmidt
Subject: Re: Passing function as a parameter in CMUCL
Date: 
Message-ID: <41717dee$0$22622$9b4e6d93@newsread4.arcor-online.net>
Andrei Stebkov schrieb:
> Maybe I shouldn't have typed the whole algorithm as the bottomline here is
> passing function as an argument.
> Is it that the Common Lisp implementation different from Scheme?
> How is it possible to pass functions as arguments in CL?
> Forgive me if my question is too newbie as I am a newbie :)

The language Common Lisp is very different from Scheme so direct
translations from Scheme code to Common Lisp are often a surprise
for newbies.

The particular issue you hit with your code is that Common Lisp has
different namespaces for functions and variables. The same symbol
can reference both a function and a variable at the same time.
Parameters to functions are variable bindings so they use the variable
namespace. If you want to call a function bound to a variable you can
use FUNCALL.

(defun foo (fn)
   (lambda (a)
     (funcall fn a)))

(funcall (lambda (x) (+ x 2)) 3)
=> 5

A related issue is how you can get the actual function object bound to
a symbol in the function namespace. This is done using the special form
FUNCTION or it's shortcut syntax #'

(funcall (function +) 1 2) => 3
(funcall #'+ 1 2) => 3

Greetings,
Jochen
From: Pascal Bourguignon
Subject: Re: Passing function as a parameter in CMUCL
Date: 
Message-ID: <878ya6mng6.fsf@thalassa.informatimago.com>
Andrei Stebkov <········@tht.net> writes:
> Error in KERNEL::UNDEFINED-SYMBOL-ERROR-HANDLER:  the function F is
> undefined.
>    [Condition of type UNDEFINED-FUNCTION]

Common-Lisp is a Lisp-2, not a Lisp-1 like scheme.

You have to write (funcall f ...) because the function is stored in
(symbol-value f), not in (symbol-function f).


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

Voting Democrat or Republican is like choosing a cabin in the Titanic.
From: Marco Antoniotti
Subject: Re: Passing function as a parameter in CMUCL
Date: 
Message-ID: <4172B9BD.8000205@cs.nyu.edu>
Hi

first of all, Common Lisp has two name spaces for functions and values. 
  Hence calling a passed-in function requires one extra jump.

Secondly, Common Lisp has different machinery to define local functions.

Third, Common Lisp has powerful loops,  but let's skip that.

Andrei Stebkov wrote:
> Hi,
> 
> Watching the video lecture of "Structure and Interpretation of Computer
> Program" I decided to reproduce the algorithm of finding a square root in
> my CMUCL environment.
> 
> That's what I defined (trying to follow as close as possible the lecturer):
> 
> (defun fixed-point (f start)
>   (setq tolerance 0.0001)
>   (defun close-enuf? (u v)
>     (< (abs (- u v))
>        tolerance))
>   (defun iter (old new)
>       (if (close-enuf? old new)
>    new
>    (iter new (f new))))
>   (iter start (f start)))

The following should work (untested)

(defun fixed-point (f start &optional (tolerance 0.00001))
     (labels ((close-enough-p (u v)
                 (< (abs (- u v)) tolerance))
              (iter (old new)
                 (if (close-enough-p old new)
                    new
                    (iter new (funcall f new)))
              )
        (iter start (funcall f start))))

The FUNCALL bit is needed because of the two namespaces for functions 
and for values.  The reason also goes deeper than that, but you can 
google for it. :)

Cheers
--
marco





> 
> (defun avg (a b)
>   (/ (+ a b) 2.0))
> 
> (defun sqrt-1 (x)
>   (fixed-point 
>    (lambda (y)(avg (/ x y) y))
>    1))
> 
> (sqrt-1 2)
> 
> Having evaluated all the defines in sequence I got the error:
> 
> Error in KERNEL::UNDEFINED-SYMBOL-ERROR-HANDLER:  the function F is
> undefined.
>    [Condition of type UNDEFINED-FUNCTION]
> 
> Maybe I shouldn't have typed the whole algorithm as the bottomline here is
> passing function as an argument.
> Is it that the Common Lisp implementation different from Scheme?
> How is it possible to pass functions as arguments in CL?
> Forgive me if my question is too newbie as I am a newbie :)
> 
> Thanks,
> Andrei