It might have been easier to just do something like this for default values of optional arguments:
(dsb (&o (p 100)) foo
(body))
=>
; put default values here
(with (p 100
,tree foo)
; do the checking here
(if ,tree
(= p (car tree)))
(body))
Edit: Personally I'd do a recursive expansion of the optional/keyword part, successively deciding at each sublist whether it should go to an optional or a keyword argument, or if the sublist is empty, to stop parsing. This would probably reduce significantly the overhead of nth, which I think needs to measure the length of the argument list each time. Will think of an alternative method of expressing dsb in a recursive manner which would hopefully just significantly increase the apparent complexity of the generated code while gaining a minor boost in efficiency.
"Personally I'd do a recursive expansion of the optional/keyword part"
I'll be honest, I am just a simple application programmer, I was stunned for example by the expansion of withs.
And I am just a muddy Common Lisper, I am not smart like the Lisp-1 guys, I do not know how to express the number 3 as a half-dozen nested lambda forms. So...
...that's a long way of saying I think you are right, there is almost definitely a nicer lambda-based solution out there. I would say I would love to see it except I doubt I would understand, I have been to Lisp-1 talks and never understood a word, I've stopped going.
But I would enjoy seeing a recursive solution, your approach sounds promising and even easy to read, more than I can say for mine.
Turns out that 'withs is recursive enough for this ^^.
(mac dsb (params data . body)
(let (reqs keys opts) (dsb-params-parse params)
(w/uniq (tree kvs)
(withs (optfn
(afn (l)
`()))
; turn reqs into the argument list, adding
; the ,tree as a rest argument
(if (no reqs)
(= reqs tree)
((afn (l)
(aif (cdr l)
(self it)
(= (cdr l) tree)))
reqs))
`(withs (,reqs ,data
,@(mappend [list (carif _)
`(do1 (if ,tree
(car ,tree)
,(cadrif _))
(= ,tree (cdr ,tree)))]
opts)
,kvs (pair ,tree)
,@(mappend [list (carif _)
; don't use aif - dsb might be
; used itself in an aif context
(w/uniq it
`(let ,it (assoc ',(carif _) ,kvs)
(if ,it
(cadr ,it)
,(cadrif _))))]
keys))
,@body)))))
Yep, I concede. The recursive solution won't easily handle the cases in http://arclanguage.org/item?id=4423 . So this is really the best way to do it ^^.
Ha, ha, yeah right, I don't even use any lisplike programming languages in an application I've ever passed to a client (using a lisplike to generate an application in a non-lisplike is another statement).
...that's a long way of saying no, I'm not even a simple application programmer, I bet you've built more Lisp code that actually reached application level.
Anyway I'll be doing my hacking now, will come back in a few dozen minutes.
It's problematic for a recursive solution. ^^ So is the second. ^^ In the end I decided that the sketch up of your solution is better, since 'withs is, after all, recursive ^^