I've been struggling with a macro kinda like once-only. You hear a lot about how nested backquotes and double commas are difficult. Are they necessary? Can't you simply refactor them into a macro that expands into a second macro?
Anybody have hard-won tips on dealing with them? A particularly hard nested-backquote macro to show off?
I've been wondering the same thing! It seems like macros warrant being even more carefully factored and "functional" than functions do, since they're so error-prone.
Looking forward to hearing what others have to say about this.
Update: I've noticed rocketnia can be good at keeping his macros well-factored. Lots of one-liners in kernelish.arc [1]:
Since then, I've noticed that defining one-use auxiliary functions like 'fn-fx and 'fn-fexport for macros is nifty in a few ways:
- Less need for w/uniq.
- More straightforward expansions and fewer gensyms when debugging.
- More one-liners, ironically at the expense of brevity. (The argument list is usually written three times this way: Once in the macro signature, once in the function signature, and once in the macro body.) At least it's in bite-size pieces. ^_^;
I've also noticed that 'after and 'protect have the same pattern, and that at least one other person here (don't remember who) uses it as extensively as I do. So it's probably as good as advertised. :-p
Yes, I find I' often write a macro whose only purpose is to allow a "body" to be written without having to enclose it in a function. For this specialized purpose, it'd be nice to have a macro defining macro to do that... though I haven't thought about how to do that myself yet.
It could technically use another helper: It's a macro that abstracts away an act of backquoting, but there could be a function that abstracts away that backquoting at some point (the macro generating a function call that uses its own backquote form). Since that's not actually "nested macro calls," maybe it doesn't count. ^^
Anyway, I think it's a perfectly legitimate use of nested backquotes.
You hear a lot about how nested backquotes and double commas are difficult.
Well, that link is possibly the first place I've heard it claimed in a general way (not counting individual people having trouble with them), and it was pretty surprising to me....
Do you think it's because of the generating-code-to-generate-code premise itself or just because of idiosyncrasies in the way layers of quoting interfere with each other in the forms of ,', and backslash-doubling?
The couple of times I've tried it I find I get tangled up in how I want to interleave macroexpansion vs evaluation. I'm sure I don't know all the tools available to me (', / ,, / ,', / ,,@ / ...)
I should try to come up with a simple example. Perhaps the canonical one is Peter Norvig's once-only that that link refers to (which also says nested backquotes are hard). I believe it's come up multiple times here, e.g. http://www.arclanguage.org/item?id=9918
Hold on, lemme push my latest commit and break wart on github :) Now you can try to make sense of my struggles at https://github.com/akkartik/wart/blob/9bd437782d6c3e862ae388... if you're so moved. (There's a 'Desired' comment halfway down which shows what I'm trying to get, and the testcase is right at the bottom of the file.)
So far nested backquotes are the only thing I've found that remained hard after using unit tests.
I think your desired behavior is wrong. You'd like the inner body of a once-only definition to be like this:
`(let* (($x o$x))
(+ ,$x 1))
But the macro user would write that body as `(+ ,$x 1), with the backquote and everything, and you don't have that backquote in your hypothetical expansion. What you're probably looking for is:
`(let* (($x o$x))
,`(+ ,$x 1))
Or, more accurately:
`(let* (($x o$x))
,(progn `(+ ,$x 1))) ; listing all the expressions in the body
Sorry, that's all the time I have to look at it right now. XD
Also, this isn't much of a response to the "generally hard" topic (except to prove this example takes more thought than I've given it so far :-p ).