Hey, this is promising work so far. Couple of observations:
1. FYI, uniq doesn't take any arguments in vanilla Arc:
arc> (syntax-quote (a@ b c))
Error: "procedure ar-gensym: expects no arguments, given 1: a@"
I'm apparently the sole weirdo who doesn't use Anarki at all, so I had to change this. It's not really necessary for the functioning of this macro, so no biggie.
2. In Arc, the t would be implied by if having an odd number of clauses:
3. The uniqs!exp ssyntax stands for (uniqs 'exp) (quoted argument), when you want (uniqs exp) (unquoted argument). You could either write (uniqs exp) by hand, or else use uniqs.exp. As it stands now, this is a bug because you're always looking up the same hash table key, namely 'exp:
arc> (syntax-quote (a@ b c))
(gs1745 b c)
arc> (syntax-quote (a@ b@ c))
(gs1746 gs1746 c)
arc> (ssexpand 'uniqs!exp)
(uniqs (quote exp))
arc> (ssexpand 'uniqs.exp)
(uniqs exp)
4. It has several problems including relying on quasiquote
5. it autogensyms every symbol that ends with "@" within exp, even if it was unquoted first
Simple to fix, if it is an issue:
(mac syntax-quote (exp)
(let uniqs (table)
(list 'quasiquote
((afn (exp)
(if (auto exp) (or= uniqs.exp (uniq))
(atom exp) exp
(unquoted exp) exp
(map self exp)))
exp))))
(def auto (exp)
(and (atom exp) (endmatch "@" (string exp))))
(def unquoted (exp)
(or (caris exp 'unquote)
(caris exp 'unquote-splicing)))
arc> (let a@ 'd (syntax-quote (a@ b c)))
(gs1758 b c)
arc> (let a@ 'd (syntax-quote (,a@ b c)))
(d b c)
6. I was hoping that by fixing these problems we could easily replace quasiquote with syntax-quote (make ` be syntax-quote instead of quasiquote) because it should make writing macros easier.
Could also just hook into mac instead of quasiquote, as in http://www.letoverlambda.com/index.cl/guest/chap3.html#sec_5 This would be an easier way to extend vanilla Arc: just redefine the mac macro, or else define a variant of it if you need to preserve the old "raw" behavior.
I managed to implement a version that redefines mac. If people want mac to stay the same we could just switch them so defmacro becomes the new version and mac remains the same. I realized that I actually liked the fact that it autogensyms the symbols that are within an unquote because otherwise you would still need to use uniq in cases where you quote inside of an unquote and you need the symbols to be the same.
First of all thanks for finding 3, I only tested the code very in very simple cases.
In response to 2, when I am reading lisp code in the format you suggested, I cannot tell whether the else case is actually part of the clause above it or is actually an else case. I just use t to make it explicit that this is the else case.
And I agree with you for 6. We should just extend mac so that it autogensyms the code it is given. There is no harm in doing this since all of the code previously written should still work.
Yeah, I too like not relying on an implicit 'else'. In fact, I use :else instead of t to be even more clear.
This is all most excellent. Don't be afraid to commit and push! Feel free to override the default mac if there aren't any obvious problems. There aren't very many people using anarki, and we can always roll it back later if necessary.