help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: defun vs lambda


From: weber
Subject: Re: defun vs lambda
Date: Fri, 31 Jul 2009 04:41:43 -0700 (PDT)
User-agent: G2/1.0

On Jul 24, 6:46 pm, p...@informatimago.com (Pascal J. Bourguignon)
wrote:
> weber<hug...@gmail.com> writes:
> > Hi,
>
> > I know I can return a function from another function, like this:
>
> > (setq f (lambda () 2))
>
> > but I have to call it like (funcall f). Is there anyway that I could
> > do:
>
> > (setf f (defun () 2) and then be able to call (f) ?
>
> Notice that funcall accepts various kinds of "functions":
>     - symbols naming functions,
>     - lambda expressions representing anonymous functions,
>     - byte code (compiled-functions),
>     - primitives ("subr" functions),
>     and possibly others (such as macros).
>
> (defun plus (x y) (+ x y))
> (defun compiled-plus (x y) (+ x y))
> (byte-compile 'compiled-plus)
>
> (let ((lambda-expression            (quote         (lambda (x y) (+ x y))))
>       (anonymous-function           (function      (lambda (x y) (+ x y))))
>       (compiled-anonymous-function  (byte-compile '(lambda (x y) (+ x y))))
>       (function-name                (quote    plus))
>       (named-function               (function plus))
>       (compiled-named-function      (function compiled-plus))
>       (interpreted-function         (symbol-function 'plus))
>       (compiled-function            (symbol-function 'compiled-plus))
>       (primitive-function           (symbol-function '+)))
>    (dolist (name  '(lambda-expression anonymous-function
>                     compiled-anonymous-function function-name named-function
>                     compiled-named-function interpreted-function
>                     compiled-function primitive-function))
>      (insert (format "%s\n\t--> %S\n\t==: %S\n\t==> %S\n\n"
>                      name (symbol-value name) (type-of (symbol-value name))
>                      (funcall (symbol-value name) 32 10)))))
>
> lambda-expression
>         --> (lambda (x y) (+ x y))
>         ==: cons
>         ==> 42
>
> anonymous-function
>         --> (lambda (x y) (+ x y))
>         ==: cons
>         ==> 42
>
> compiled-anonymous-function
>         --> #[(x y) "   \\\207" [x y] 2]
>         ==: compiled-function
>         ==> 42
>
> function-name
>         --> plus
>         ==: symbol
>         ==> 42
>
> named-function
>         --> plus
>         ==: symbol
>         ==> 42
>
> compiled-named-function
>         --> compiled-plus
>         ==: symbol
>         ==> 42
>
> interpreted-function
>         --> (lambda (x y) (+ x y))
>         ==: cons
>         ==> 42
>
> compiled-function
>         --> #[(x y) "   \\\207" [x y] 2]
>         ==: compiled-function
>         ==> 42
>
> primitive-function
>         --> #<subr +>
>         ==: subr
>         ==> 42
>
> nil
>
> The difference between quote and function, in emacs lisp, can be
> detected only when you compile the code that use them.  function let
> the compiler know that its argument is actually code, so it will
> compile it.  quote let the compiler know that its argument is actually
> data, so it won't compile it: the lambda expression returned by quote
> will always be considered as data (and happily interpreted by emacs
> lisp).
>
> > (setf f (defun () 2) and then be able to call (f) ?
>
> This defun form is invalid. You must give a function name:
>
>    (setf f (defun g () 2))
>
> defun returns the name of the function, that is the symbol g, and f
> will be bound to that symbol.  So when you (funcall f), you will call
> the function named by g.  But you still have to write (funcall f).
>
> You can of course name the function f, and so be able to directly call
> it:
>
>     (defun f () 2)
>     (f) --> 2
>
> Now to answer your formal question, there is no way to call the
> function bound to a variable without using funcall (or apply).  This
> is because emacs lisp is what is called, a "Lisp-2".
> Have a look at:http://www.nhplace.com/kent/Papers/Technical-Issues.html
>
> When we define a function with defun, what happens, is that the value
> binding of the name of the function is not changed:
>
>     (setf f 42)
>     (defun f () 2)
>     f --> 42
>
> but instead, a function slot is changed: the symbol is "fbound".
>
>     (unintern 'f)                     ; clean up
>     (list (boundp 'f) (fboundp 'f))   ; --> (nil nil)
>     (setf f 42)                       ; --> 42
>     (list (boundp 'f) (fboundp 'f))   ; --> (t nil)
>     (defun f () 2)                    ; --> f
>     (list (boundp 'f) (fboundp 'f))   ; --> (t t)
>
> In the case of emacs lisp, which proposes only special variables, when
> the symbol is bound, you can  find the binding of a variable  in the
> value slot of the symbol:
>
>     (symbol-value 'f)                 ; --> 42
>
> Similarly, when the symbol is fbound, you can find the function
> binding of the function int he function slot of the symbol:
>
>     (symbol-function 'f)              ; --> (lambda nil 2)
>
> These operators are accessors, so you could modify the function slot
> as well as the value slot:
>
>    (setf (symbol-value 'f) 42)                   ; <=> (setf f 42)
>    (setf (symbol-function 'f) (lambda () 2))     ; <=> (defun f () 2)
>
> So in a way, you could write that:
>
>    (setf (symbol-function 'f) (lambda () 2))
>
> and then be able to call the function f directly:
>
>    (f) ; --> 2
>
> But it's simplier to write (defun f () 2).
> Unless of course you have to generate the body of the function at run-time.
>
>   (setf (symbol-function 'f) (compute-some-lambda-expression))
>   (f) ; --> ?
>   (byte-compile 'f)
>   (f) ; --> ? faster.
>
> or just:
>
>   (setf (symbol-function 'f) (byte-compile (compute-some-lambda-expression)))
>   (f) ; --> ? faster.
>
> but you didn't mention generating code at run-time, so I guess I
> overextended myself.  Sorry.
>
> --
> __Pascal Bourguignon__

Thanks Anselm.

Pascal,

I did wanted to generate code at run-time, similar to the way like
defstruct generates helper functions.

Thanks for the great explanation!
Cheers,
weber


reply via email to

[Prev in Thread] Current Thread [Next in Thread]