Suggestions for macro

2009-10-09 Thread nilamo

Hey all.  I'm pretty new to Clojure, and wanted to try my hand at
writing a macro.

'dowhile' is nothing special, but I'd still like to hear any comments/
suggestions you may have.

(defmacro dowhile [body test]
  `(do ~body (while ~test ~body)))

A test shows...
(macroexpand-1 '(dowhile (dosync (alter x inc)) ( @x 5)))
= (do (dosync (alter x inc)) (clojure.core/while ( (clojure.core/
deref x) 5) (dosync (alter x inc

And to show that it works...
(def x (ref 0))
(println @x); 0
(dowhile (dosync (alter x inc)) ( @x 5))
(println @x); 5

(dowhile (dosync (alter x dec)) ( @x 7))
(println @x); 4

Thanks in advance.

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: Suggestions for macro

2009-10-09 Thread Howard Lewis Ship

I'd tend to code this so that the test was the first form, and then
any number of additional remaining forms become the body, in an
implicit do.  Obviously, if you're writing something like this, its
for side effects.

In addition, I'd wrap the body in an annonymous function, defined in a
let, so that the code of the body only needs to exists once in the
macro.

This is off the top of my head:

(defmacro dowhile [test  body]
  `(let [body# #(~...@body)]
 (body#)
 (while ~test (body#



On Fri, Oct 9, 2009 at 12:56 PM, nilamo 7nil...@gmail.com wrote:

 Hey all.  I'm pretty new to Clojure, and wanted to try my hand at
 writing a macro.

 'dowhile' is nothing special, but I'd still like to hear any comments/
 suggestions you may have.

 (defmacro dowhile [body test]
  `(do ~body (while ~test ~body)))

 A test shows...
 (macroexpand-1 '(dowhile (dosync (alter x inc)) ( @x 5)))
 = (do (dosync (alter x inc)) (clojure.core/while ( (clojure.core/
 deref x) 5) (dosync (alter x inc

 And to show that it works...
 (def x (ref 0))
 (println @x)    ; 0
 (dowhile (dosync (alter x inc)) ( @x 5))
 (println @x)    ; 5

 (dowhile (dosync (alter x dec)) ( @x 7))
 (println @x)    ; 4

 Thanks in advance.

 




-- 
Howard M. Lewis Ship

Creator of Apache Tapestry

The source for Tapestry training, mentoring and support. Contact me to
learn how I can get you up and productive in Tapestry fast!

(971) 678-5210
http://howardlewisship.com

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: Suggestions for macro

2009-10-09 Thread nilamo

That does look better.

I had trouble with the anonymous func, however.  After working it out,
here's what I think the problem is, as well as what I did about it.
~...@body expands the body (which is a list) so that the elements of the
list are represented without the surrounding parens.  However, each
element already carried it's own parens along with it.  So when you
do:
`(let [body# #(~...@body)]
That expands to something like this:
`(let [body# #((some-fn) (another-fn))]
Which... isn't right.  I found two ways to fix this.  The first was to
wrap the splicing in a do:
`(let [body# #(do ~...@body)]
Or to create an anonymous function the long way:
`(let [body# (fn [] ~...@body)]

Either way, a working form of your improvement would be:
(defmacro dowhile [test  body]
  `(let [body# (fn [] ~...@body)]
(body#)
(while ~test (body#

Thank you, Howard, that is much better than my original version (also,
thank you for making me think.  I think I actually learned a few
things there).

On Oct 9, 4:40 pm, Howard Lewis Ship hls...@gmail.com wrote:
 I'd tend to code this so that the test was the first form, and then
 any number of additional remaining forms become the body, in an
 implicit do.  Obviously, if you're writing something like this, its
 for side effects.

 In addition, I'd wrap the body in an annonymous function, defined in a
 let, so that the code of the body only needs to exists once in the
 macro.

 This is off the top of my head:

 (defmacro dowhile [test  body]
   `(let [body# #(~...@body)]
      (body#)
      (while ~test (body#



 On Fri, Oct 9, 2009 at 12:56 PM, nilamo 7nil...@gmail.com wrote:

  Hey all.  I'm pretty new to Clojure, and wanted to try my hand at
  writing a macro.

  'dowhile' is nothing special, but I'd still like to hear any comments/
  suggestions you may have.

  (defmacro dowhile [body test]
   `(do ~body (while ~test ~body)))

  A test shows...
  (macroexpand-1 '(dowhile (dosync (alter x inc)) ( @x 5)))
  = (do (dosync (alter x inc)) (clojure.core/while ( (clojure.core/
  deref x) 5) (dosync (alter x inc

  And to show that it works...
  (def x (ref 0))
  (println @x)    ; 0
  (dowhile (dosync (alter x inc)) ( @x 5))
  (println @x)    ; 5

  (dowhile (dosync (alter x dec)) ( @x 7))
  (println @x)    ; 4

  Thanks in advance.

 --
 Howard M. Lewis Ship

 Creator of Apache Tapestry

 The source for Tapestry training, mentoring and support. Contact me to
 learn how I can get you up and productive in Tapestry fast!

 (971) 678-5210http://howardlewisship.com

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---