Looking at my library of macros, I find that about half of them are used simply to quote parameters. I spend a lot of time writing dsl logic, where this is frequently needed, but I suspect others have many of these macros as well. For example, suppose you need a convenience function for adding a prefix to a symbol: > (= x 'bar)
> (addpref foo x)
foobar
This is how I would write this command: (def addpref1 (a b)
(sym (string a b)))
(mac addpref (a b)
`(addpref1 ',a ,b))
The goal here is to minimize the complexity of the macro by delegating everything besides the quotation of the parameter to a helper function. But having macros just to quote parameters feels a bit like overkill and makes for bulky code. It also pollutes the namespace with a helper function name. Couldn't there be a better way?I present my solution- A version of "def" enhanced to allow destructuring of quotation marks! (mac defq (nam parms . body)
(let unquoted [and (acons _) (is 'unquote car._)]
(if (find unquoted parms)
(with (nuparms (map [if unquoted._
cadr._
_]
parms)
zparms (map [if unquoted._
(list 'quote _)
(list 'unquote _)]
parms)
x (uniq))
`(do (def ,x ,nuparms
,@body)
(mac ,nam ,nuparms
(,'quasiquote (,x ,@zparms)))))
`(def ,nam ,parms ,@body))))
This command supports everything "def" can do: > (defq mycons (a b)
(cons a b))
#<procedure: mycons>
> (mycons 1 2)
(1 . 2)
The magic of this command is that quotes marks can be "unquoted" in the parameter list- If you think it through, it makes perfect sense to allow this. Here is a version of addpref defined with defq: > (defq addpref (,a b)
(sym (string a b)))
#3(tagged mac #<procedure>)
Notice that defq detected the unquoting of a parameter and therefore generated a macro instead of a function. Let's try to use this command now: > (= x 'bar)
> (addpref foo x)
foobar
...and there you go: It behaves and looks just like a regular function created with "def", but one of its parameters has been magically quoted!There is no technical or performance limitation that would prevent including this kind of functionality in the standard "def" command, if this was to prove useful enough to be justified. This initial version only supports unquoting of parameters without other types of destructuring, but it would be relatively straight-forward to extend this approach to supporting unquoting along with arbitrary destructuring. In fact, it could even (if one were crazy enough to implement this) be used to unify "mac" and "def" into a single operation- and I think it might be a pretty elegant unified command... |