[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