| (Followup to http://arclanguage.org/item?id=13364, http://arclanguage.org/item?id=13377) Here's mac in wart from a few commits ago, parsing keyword args, rest args, destructuring, optional args: (defmacro$ mac0(name params &body body)
`(defmacro$ ,name(&rest ,$args)
,(compile-params params $args body)))
(defmacro$ simply replaces $args with an appropriate gensym: http://arclanguage.org/item?id=13342)Inspired by Doug Hoyte, I wanted to implement once-only args so I could say, for example, (mac iflet(var o$expr then . rest)
`(if ,$expr
(let ,var ,$expr
,then)
,@rest))
instead of (mac iflet(var expr then . rest)
`(let ,$expr ,expr
(if ,$expr
(let ,var ,$expr
,then)
,@rest)))
o$var automatically gets bound to gensym $var.Here's how to do that, closely paralleling defmacro! at http://letoverlambda.com/lol.lisp: (defmacro$ mac(name params &body body)
(let* (($os (remove-if-not #'odollar-symbol-p (strip-rest params)))
($s (mapcar #'odollar-symbol-to-dollar-symbol $os)))
`(mac0 ,name ,params
`(let ,(mapcar #'list (list ,@$s) (list ,@$os))
,(progn ,@body)))))
I have it, and yet I don't fully understand it. rocketnia helped immeasurably with http://arclanguage.org/item?id=13379[1] so now I get the ,(progn ,@body). It's to allow body to be a (third!) backquoted expression. But I still don't get the (list ,@$s). Why doesn't just $s work?I think one reason nested backquotes are hard is that they expand into gibberish. wart> (macex1 '(mac foo(n) `(+ 1 ,n)))
(mac0 foo (n)
`(let* (sb-impl::backq-comma (mapcar #'list (list) (list)))
,(progn `(+ ,1 ,n))))
Looking at that you can't tell it's right. You can run the program and see that it works, of course, but when it doesn't work you can't tell if your attempted changes are on the right track. As a result I spent most of my time flailing around without the (list ,@var) pattern in my attempts. As before, any and all tips most appreciated.[1] The clearest thing you've ever ever written, rocketnia :) |