;; from: ;; (build-cond-action-pairs "fish are cool" (incf var-a) ;; "amphibians are cool" (incf var-b)) ;; the macro-expansion should be: ;; (("fish are cool" (incf var-a)) ("amphibians are cool" (incf var-b))) ;; of course, this is makeable - with common lisp.
However, macro's are then executed - and execution of this is not possible because the first position of this list ("fish are cool" (incf var-a)) doesn't return a function.
But if the macro-expansion is
;; (list '("fish are cool" (incf var-a)) '("amphibians are cool" (incf var-b))) ;; which is equivalent to: ;; (list (quote ("fish are cool" (incf var-a))) (quote ("amphibians are cool" (incf var-b)))) ;; it would evaluate to: ;; (("fish are cool" (incf var-a)) ("amphibians are cool" (incf var-b)))
This would be regular lisp.
Although it does not expand to a valid lisp expression, we can achieve it even that it expands really to:
(("fish are cool" (incf var-a)) ("amphibians are cool" (incf var-b)))
Because using macroexpand-1 you can check to what the macro expands to - no matter whether the evaluation of the expanded expression will give an error or not. So I will show you both possibilities.
;; we want ;; (macroexpand-1 '(build-cond-action-pairs "fish are cool" (incf var-a) ;; "amphibians are cool" (incf var-b))) ;; returns: ;; (("fish are cool" (incf var-a)) ("amphibians are cool" (incf var-b))) (defmacro build-cond-action-pairs (&rest var) ...) ;; so we want this macro loops over its var elements and pairs the elements. ;; we need a function which takes a list and generates a list of lists ;; where the inner lists group pairs of elements. ;; One can achieve this with loop. (defun to-pairs (l) "Group elements of list l in lists of length 2 - pairs." (loop for (a b &rest x) on l by #'cddr collect (list a b))) ;; a macro takes its arguments list and doesn't evaluate its arguments. ;; we can use inside macros such functions to re-arrange the arguments list ;; - we can use list/data manipulation functions to re-arrange code - this ;; is the power of macros in common lisp! (defmacro build-cond-action-pairs (&rest var) `,(to-pairs `,var)) ;; try it out: (macroexpand-1 '(build-cond-action-pairs "fish are cool" (incf var-a) "amphibians are cool" (incf var-b))) ;; returning: (("fish are cool" (INCF VAR-A)) ("amphibians are cool" (INCF VAR-B))) ; T
So this expands exactly to how you want it. But when executing the macro there will be an error:
(build-cond-action-pairs "fish are cool" (incf var-a) "amphibians are cool" (incf var-b)) *** - EVAL: ("fish are cool" (INCF VAR-A)) is not a function name; try using a symbol instead The following restarts are available: USE-VALUE :R1 Input a value to be used instead. ABORT :R2 Abort main loop
(I tried it out in the implementation clisp of common lisp - just because I use it for very quick tests often - while for serious programming I use emacs + sbcl).
I wanted just to demonstrate you that lisp can do even this.
So let's build the other variant with list and quote:
(defun to-quoted-pairs (l) "Group elements of list l in quoted lists of length 2 - quoted pairs." (loop for (a b &rest x) on l by #'cddr collect (list 'quote (list a b)))) (defmacro build-cond-action-pairs (&rest var) `,(to-quoted-pairs `,var)) (macroexpand-1 '(build-cond-action-pairs "fish are cool" (incf var-a) "amphibians are cool" (incf var-b))) ;;=> ('("fish are cool" (INCF VAR-A)) '("amphibians are cool" (INCF VAR-B))) ;;=> T
This is nearly what we want - we just want to cons a #'list at the start. So:
(defmacro build-cond-action-pairs (&rest var) (cons 'list `,(to-quoted-pairs `,var))) (macroexpand-1 '(build-cond-action-pairs "fish are cool" (incf var-a) "amphibians are cool" (incf var-b))) ;;=> (LIST '("fish are cool" (INCF VAR-A)) ;;=> '("amphibians are cool" (INCF VAR-B))) ; ;;=> T ;; That's it! and we can run it without error: (build-cond-action-pairs "fish are cool" (incf var-a) "amphibians are cool" (incf var-b)) ;;=> (("fish are cool" (INCF VAR-A)) ("amphibians are cool" (INCF VAR-B)))
Voila! We made it!
'(incf var-a)or(quote (incf var-a))(but what do you want to do etc).