Hi Mark, Am 17.12.2008 um 23:48 schrieb Mark Volkmann:
Here's an example from Stuart Halloway's book.(defmacro chain ([x form] (list '. x form)) ([x form & more] (concat (list 'chain (list '. x form)) more)))(macroexpand '(chain arm getHand getFinger getNail) ; I added the getNail part.The result is (. (. (. arm getHand) getFinger) getNail) I'm having trouble understanding how this works. In the first call, x is arm, form is getHand, and more is '(getFinger getNail), right? I expected that more would be processed recursively, but it seems to me that only form is processed recursively. Somebody please straighten me out here.
Just step through it step-by-step: (chain arm getHand getFinger getNail) First expansion: x = arm, from = getHand, more = (getFinger getNail) => (concat (list 'chain (list '. x form)) more) => (concat (chain (. arm getHand)) (getFinger getNail)) => (chain (. arm getHand) getFinger getNail)Second expansion: x = (. arm getHand), form = getFinger, more = (getNail)
=> the rest is as above. It works similar to the -> macro from clojure.core. It basically calls itself on the result of the previous call until all remaining arguments are consumed. I don't know the context in which this macro is shown, and I don't want to step on anyone's toes, but it should be using syntax-quote: (defmacro chain ([x form] `(. ~x ~form)) ([x form & more] `(chain (. ~x ~form) ~...@more))) I think also makes the way it works clearer visible, IMHO. syntax-quote should be the standard way to write macros and we should encourage its use as much as possible. The original macro has a problem, when the user defines a chain macro on its own. This is captured by the above expansion. This could be solved by using `chain instead of 'chain. Still, I think the syntax-quote form is clearer on what's happening. Hope this helps. Sincerely Meikel
smime.p7s
Description: S/MIME cryptographic signature