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

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

Re: Difficult macro question: Doing custom `let'


From: Pascal Bourguignon
Subject: Re: Difficult macro question: Doing custom `let'
Date: 18 Aug 2003 23:20:57 +0200
User-agent: Gnus/5.09 (Gnus v5.9.0) 21.3.50.pjb1.1

jari.aalto@poboxes.com (Jari Aalto+mail.emacs) writes:

> I'm trying to make a custom `let' macro. The basic idea is that
> the variables defined inside `let' should be user defined and
> the `let' form simply should set them to nil. Something like:
> 
> (setq list '(a b c))
> 
> Something, a macro, that turns that into:
> 
>    (let (a
>          b
>          b)

Are you aware  that this is exactly the behavior of  normal let, be it
form emacs lisp or from Common-Lisp?

    (let (a b c) (insert (format "==> a=%s b=%s c=%s\n" a b c)))

    ==> a=nil b=nil c=nil


 
> I've experimented with this:
> 
>   (nconc 
>    (list 'let)
>    (list
>     (mapcar 
>      (function
>       (lambda (x)
>         (list x nil)))
>      list)))
> --> (let ((a nil) (b nil) (c nil)))
> 
> Now the problem is, How Do I make a macro that does exactly that above?
> The macro would be called inside function body:
> Now, how do I get there?

A macro  is merely a function,  only that it executes  at compile time
instead of at run time.  So:

    (defmacro my-let (var-list &rest body)
      (nconc 
       (list 'let)
       (list
        (mapcar 
         (function
          (lambda (x)
            (list x nil)))
         var-list))
         body))

    (show (macroexpand '(my-let (a b c) (statement1) (statement2))))
    ==> (let ((a nil) (b nil) (c nil)) (statement1) (statement2))

Now, when you write macros (and sometimes in plain functions), you may
use  with  great  benefit  backquote/coma constructs.   The  backquote
introduce a "literal" construct, like  the quote, only that inside it,
anything  introduced by  a coma  is  evaluated, and  ,@ introduce  the
elements of an evaluated list.

This allow you to write a result as a template with some values:

    (defmacro my-let (var-list &rest body)
        `(let ,(mapcar (lambda (x) (list x nil)) var-list)
              ,@body))

    (show (macroexpand '(my-let (a b c) (statement1) (statement2))))
    ==> (let ((a nil) (b nil) (c nil)) (statement1) (statement2))


Note that  it's (mapcar  (lambda (x) (list  x nil)) var-list)  and the
symbol body  that are  evaluated.  The mapcar  returns a list  that is
inserted  as  is,  and  the   evaluation  of  body  returns  the  list
((statement1) (statemet2)) of which the elements are inserted.

-- 
__Pascal_Bourguignon__                   http://www.informatimago.com/
----------------------------------------------------------------------
Do not adjust your mind, there is a fault in reality.


reply via email to

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