Re: defmacro



"Kim Russell" <kimrru@xxxxxxxxx> writes:

Hi,

I'm writing a defmacro which expands to a do loop and calls an
iterator. I think I have most of it done but the do syntax is kind of
confusing.
Any help would be appreciated. I apologize if it's not the best syntax.

(defmacro doloop (vars &body body)
(let ((arg (gensym))
(itr (gensym)))
`(let ((,arg ',(car vars))
(,itr ',(cadr vars)))
(do ((,arg() (funcall (iter-n ,itr)))
((,v ,arg) ((null (funcall (iter-has-n ,itr)) arg))))
,@body))))

You can use macroexpand and macroexpand-1:

[77]> (defmacro doloop (vars &body body)
(let ((arg (gensym))
(itr (gensym)))
`(let ((,arg ',(car vars))
(,itr ',(cadr vars)))
(do ((,arg() (funcall (iter-n ,itr)))
((,v ,arg) ((null (funcall (iter-has-n ,itr)) arg))))
,@body))))
DOLOOP
[78]> (macroexpand '(doloop (n (list-itr '(a 2 3 4)))
(format t "~A~%" n)))

*** - EVAL: variable V has no value
The following restarts are available:
USE-VALUE :R1 You may input a value to be used instead of V.
STORE-VALUE :R2 You may input a new value for V.
ABORT :R3 ABORT
Break 1 [79]>


You can give names to gensym to make it more readable, and I removed
the comma before V to obtain the following to try to understand what
you're doing.

[87] (defmacro doloop (vars &body body)
(let ((arg (gensym "ARG-"))
(itr (gensym "ITR-")))
`(let ((,arg ',(car vars))
(,itr ',(cadr vars)))
(do ((,arg() (funcall (iter-n ,itr)))
((v ,arg) ((null (funcall (iter-has-n ,itr)) arg))))
,@body))))

DOLOOP
[88]> (macroexpand '(doloop (n (list-itr '(a 2 3 4)))
(format t "~A~%" n)))
(LET ((#:ARG-5244 'N) (#:ITR-5245 '(LIST-ITR '(A 2 3 4))))
(DO
((#:ARG-5244 NIL (FUNCALL (ITER-N #:ITR-5245)))
((V #:ARG-5244) ((NULL (FUNCALL (ITER-HAS-N #:ITR-5245)) ARG))))
(FORMAT T "~A~%" N))) ;
T


I'm still puzzled. To write a macro, instead of showing the result
of "calling" the macro, you should show an example of what the macro
should expand to:

(doloop (n '(a b c)) (print n))

--(expands-to)-->

(do ((n '() (first ,itr))
(,itr '(a b c) (rest ,itr)))
((null ,itr))
(print n))

(showing with , the gensymed variables for example).
Then we could easily write a macro to do that:


(defmacro doloop ((var init-value) &body body)
(let ((itr (gensym "ITR-")))
`(do ((,var '() (first ,itr))
(,itr ,init-value (rest ,itr)))
((null ,itr))
,@body)))

If you want something else, we need more explanations...


--
__Pascal Bourguignon__ http://www.informatimago.com/
Until real software engineering is developed, the next best practice
is to develop with a dynamic system that has extreme late binding in
all aspects. The first system to really do this in an important way
is Lisp. -- Alan Kay
.



Relevant Pages

  • 2 macros and passing gensyms around
    ... when (listp var-and-column-name) ... (defmacro bind-vars ((&rest vars) ... data &body body) ... The name would be created in the with-bindable-columns macro and used in the ...
    (comp.lang.lisp)
  • Re: Reasons to choose CLISP over other free implementations
    ... (defmacro ?1 (&rest args) ... "A macro extracting the second of its arguments." ... (defmacro lret* (bindings &body body) ...
    (comp.lang.lisp)
  • Re: 2 macros and passing gensyms around
    ... when (listp var-and-column-name) ... (defmacro bind-vars ((&rest vars) ... data &body body) ... The name would be created in the with-bindable-columns macro and used in the ...
    (comp.lang.lisp)
  • Re: Newbie doubt with macros ` , ,@
    ... It is not possible to write commas inside a comma, ... macro and what should be a function. ... (defmacro let-samevars (definition &rest vars) ...
    (comp.lang.lisp)
  • Re: Another HTML generation macro
    ... > another Scheme expression, so you need a multi pass evaluation, while in my ... (defmacro table (attributes &body body) ... you'd write a macro to generate them... ...
    (comp.lang.lisp)

Loading