While looking to exclude the uses of the list
function through the backquote substitutes in defmacro
s, my attempt failed when combined with the let
and `let*
recipe, together with the gensym
function (as a source of unintern
ed symbols, as illustrated somewhere else), to create temporary variables - but the latter is not the issue.
A running MWE [EDITED: inserted macroexpand] is the following.
(defun w (a &optional b) ; line 1
(let ((z (gensym)))
`(let* ((,z (if (integerp ,b) '((,a ,b)) '((,a))))) ,z)))
⇒ w
(eval (w 3)) ; line 2
⇒ ((3))
(eval (w 3 0)) ; line 3
⇒ ((3 0))
The w
is a defun
above: when the optional integerp
second argument is present, return the pair as a "doubled" list; otherwise return only the first argument, also inside two pairs of parentheses.
Now comes the tricky part: need to replace the defun
with a defmacro
(m
for w
).
(defmacro m (a &optional b) ; line 4
(let ((z (gensym)))
`(let* ((,z (if (integerp ,b) `((,a ,b)) `((,a))))) ,z)))
⇒ m
(macroexpand (m (+ 1 2) 0)) ; line 5
⇒ list: Symbol's value as variable is void: a
And also attempt to return the evaluation of (+ 1 2)
, i.e., ((3 0))
. The loop shows the above line #4
is faulty.
Next use instead simple quotes, i.e., '((,a ,b))
.
(defmacro m (a &optional b) ; line 6
(let ((z (gensym)))
`(let* ((,z (if (integerp ,b) '((,a ,b)) '((,a))))) ,z)))
⇒ m
(macroexpand (m (+ 1 2) 0)) ; line 7
⇒ (((+ 1 2) 0))
Okay, but there is no evaluation of the argument: not acceptable.
(defmacro m (a &optional b) ; line 8
(let ((z (gensym)))
`(let* ((,z (if (integerp ,b) (list (list ,a ,b)) (list (list ,a))))) ,z)))
⇒ m
(macroexpand (m (+ 1 2) 0)) ; line 9
⇒ ((3 0))
Finally, use the list
function for a change: this time it works, yet there is one list
too many.
The problem is then how can line #4
keep its minimalistic form using (back)quotes, so that line #5
would result as line #3
- using defmacro
versus defun
. There is a `(...
within `(---
pattern. that might be the cause.
Appreciate all answers. Thank s.