Mészáros Levente wrote:
Would you like to show more elaborate loop examples?
Let's say one has a list and one wants to transform it into a string by transforming each element to a string and putting a comma between them. (concatenate-as-string (iter (for e in l) (except-first-time (collect ", ")) (collect (as-string e))))
I recently came across that article about Lispy FORMAT replacements and started wondering how to nicely implement FORMAT's "~^" idiom.
http://www.cs.yale.edu/homes/dvm/format-stinks.html
BTW, I haven't seen the code for McDermott's out macro, but I expect it to be subject to code-walking problems similar to Iterate, series and other packages that depend on traversing code.
Why? consider one example from the above article: (out "#<Foo " (Foo-label f1) (:q ((eq (Foo-status f1) ':abnormal) "?")) (:e (dolist (x (Foo-contents f1)) (:o " " x))) ">") Do you see the :o keyword inside the dolist? I think keywords are constants and cannot be locally bound (using MACROLET). Therefore, I believe the OUT macro needs to code-walk its body to track down all uses of :o and insert the replacememt code.
Had a non-constant symbol been used therein, then MACROLET could have been used and the implementation of the macro out would (presumably) be clean.
In any case, ~^ is quite different from *-first-time. It's more like an early test of loop termination. The macro out does not propose an idiom for that. The examples just repeat the termination test, as in (defun print-xapping ...) ... (do ((d ... (cdr d))) ... (:q ((not (null (cdr d))) " "))))) Repeating the test makes it unable to use the much more readable DOLIST instead of DO, and therefore must also use (CAR d) to access the elements.
Reading the full paper (ytools) instead of the short FORMAT critique, it appears to me that OUT is no silver bullet either. It has its own set of controls: :a, :e, :t, :i>, :i<, :f, :v, :pp-block etc., so it's still complex to grok. I found the difference more appealing between e.g. the sexp-based regular expression notation (IIRC there's a Scheme SRFI about it) that the error-prone flat string syntax.
BTW, McDermott's diver&snorkeler macro design pattern is interesting.
Regards, Jörg Höhle
Today, Joerg-Cyril Hoehle Joerg-Cyril.Hoehle@t-systems.com wrote:
Mészáros Levente wrote:
Would you like to show more elaborate loop examples?
Let's say one has a list and one wants to transform it into a string by transforming each element to a string and putting a comma between them. (concatenate-as-string (iter (for e in l) (except-first-time (collect ", ")) (collect (as-string e))))
I recently came across that article about Lispy FORMAT replacements and started wondering how to nicely implement FORMAT's "~^" idiom.
http://www.cs.yale.edu/homes/dvm/format-stinks.html
BTW, I haven't seen the code for McDermott's out macro, but I expect it to be subject to code-walking problems similar to Iterate, series and other packages that depend on traversing code.
Why? consider one example from the above article: (out "#<Foo " (Foo-label f1) (:q ((eq (Foo-status f1) ':abnormal) "?")) (:e (dolist (x (Foo-contents f1)) (:o " " x))) ">") Do you see the :o keyword inside the dolist? I think keywords are constants and cannot be locally bound (using MACROLET). Therefore, I believe the OUT macro needs to code-walk its body to track down all uses of :o and insert the replacememt code.
I looked over the code and it seems like he did use a code walker for the OUT macro. But brace yourself: You /can/ bind keywords to functions in LABELS forms, you can even do that in the global environment via defun or defgeneric. Keywords are constants, but that affects only their value binding, not function bindings.
Had a non-constant symbol been used therein, then MACROLET could have been used and the implementation of the macro out would (presumably) be clean.
I'm pretty sure that's how I would have done it. TBH, I'm fairly surprised he did use a code walker for OUT.
[snip]
Reading the full paper (ytools) instead of the short FORMAT critique, it appears to me that OUT is no silver bullet either. It has its own set of controls: :a, :e, :t, :i>, :i<, :f, :v, :pp-block etc., so it's still complex to grok. I found the difference more appealing between e.g. the sexp-based regular expression notation (IIRC there's a Scheme SRFI about it) that the error-prone flat string syntax.
Agreed. OUT looks like a not-so-great implementation of an otherwise good idea. I'd like to see it done right (-:
BTW, McDermott's diver&snorkeler macro design pattern is interesting.
Haven't seen that yet. Will keep an eye out (-:
Cheers,