Re: Hierarchical logs

2012-02-15 Thread jweiss
Unfortunately it doesn't call the functions/macros that the pprint
code says are meant for custom dispatch:

pprint-logical-block
pprint-newline
pprint-indent
etc

Wish I could find an example of those being used in a custom dispatch,
I made a lame attempt and for some reason my custom dispatch printed
nothing at all :) I can dig in and figure it out, but it would be
quicker if someone has already been there.  Surely someone has done
this :)

-jeff

On Feb 15, 3:02 am, Kevin Downey redc...@gmail.com wrote:
 https://gist.github.com/1314616is a small example of a custom
 dispatch, doesn't do custom indenting though









 On Tue, Feb 14, 2012 at 6:33 PM, jweiss jeffrey.m.we...@gmail.com wrote:
  It occurred to me that ultimately what I want is just a pretty-printed
  output that I can put on a webpage and apply syntaxhighlighter to.

  I should be able to use a custom pprint dispatch to take this
  [[(+ 5 (- 4 2 (* 9 3)) (* 5 (+ 6 3))) nil]
   [(- 4 2 (* 9 3)) nil]
   [(* 9 3) nil]
   [27 true]
   [-25 true]
   [(* 5 (+ 6 3)) nil]
   [(+ 6 3) nil]
   [9 true]
   [45 true]
   [25 true]]

  and print something like this:

  (+ 5 (- 4 2 (* 9 3)) (* 5 (+ 6 3)))
   (- 4 2 (* 9 3))
     (* 9 3)
     27
   -25
   (* 5 (+ 6 3))
     (+ 6 3)
     9
   45
  25

  Without even converting it into a tree.  But I am having a hard time
  finding an example of custom dispatch, or docs on how to write one.  I
  really just want things printed the same as pprint currently does, but
  being able to specify extra indent for the whole block.  I had
  originally planned to output html where each item was properly nested
  as html divs, but I think that is getting overly complex.

  -jeff

  On Feb 14, 10:14 am, jweiss jeffrey.m.we...@gmail.com wrote:
  Thanks, Alan,

  The solution I used looks exactly like yours:

  (defn mktree [vz [i out?]]
    (if out?
      (- vz (zip/append-child i) zip/up )
      (- vz (zip/append-child [i]) zip/down zip/rightmost)))

  (defn as-tree [tracelist]
    (zip/root (reduce mktree (zip/vector-zip []) tracelist)))

  Thinking about it some more, I don't think I'm going to come up with a
  solution that's any more efficient or easy to code as this one.  The
  real work is figuring out where the next element needs to be
  inserted.  Zipper keeps that information as part of the data structure
  so it doesn't have to be re-calculated every iteration.  My previous
  solution using loop had kept an accumulator (a list of indices to pass
  to assoc-in).

  -jeff

  On Feb 12, 3:42 am, Alan Malloy a...@malloys.org wrote:

   I toyed with some simple ways of doing this, but I don't think any of
   them will actually work out. I think the advice you got in #clojure to
   use zippers is probably correct. Here's a sketch I bashed out that
   seems to do roughly what you want:https://gist.github.com/1807340(I
   took the liberty of wrapping the whole thing in another [] under the
   assumption you'd want to record multiple top-level calls; if not you
   can just call first on the result).

   On Feb 11, 8:39 pm, jweiss jeffrey.m.we...@gmail.com wrote:

I've been working on a tracing library, that works much like
clojure.contrib.trace (based on it, actually).   One sticky problem
I've found is, hierarchical logs are really crappy to try to stream to
a file.  You can't just keep writing to the end of the file - new data
needs to be inserted before existing end-tags.  So what I'm doing is
storing the data as a list, until I know the data is complete, and
then i turn it back into a tree to write the file.

However I can't think of a simple way to do it, even though it seems
like a simple operation.

I want to turn this list of pairs (first item is the fn call or return
value, the second is a truthy value marking whether it's a call or
return)

'[[(+ 1 (- 5 2) nil]
 [(- 5 2) nil]
 [3 true]
 [4 true]]

I want to turn that into
[(+ 1 (- 5 2))
    [(- 5 2)
     3]
 4]

Is there a simple way to do this?

  --
  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

 --
 And what is good, Phaedrus,
 And what is not good—
 Need we ask anyone to tell us these things?

-- 
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: Hierarchical logs

2012-02-14 Thread jweiss
Thanks, Alan,

The solution I used looks exactly like yours:

(defn mktree [vz [i out?]]
  (if out?
    (- vz (zip/append-child i) zip/up )
    (- vz (zip/append-child [i]) zip/down zip/rightmost)))

(defn as-tree [tracelist]
  (zip/root (reduce mktree (zip/vector-zip []) tracelist)))

Thinking about it some more, I don't think I'm going to come up with a
solution that's any more efficient or easy to code as this one.  The
real work is figuring out where the next element needs to be
inserted.  Zipper keeps that information as part of the data structure
so it doesn't have to be re-calculated every iteration.  My previous
solution using loop had kept an accumulator (a list of indices to pass
to assoc-in).

-jeff

On Feb 12, 3:42 am, Alan Malloy a...@malloys.org wrote:
 I toyed with some simple ways of doing this, but I don't think any of
 them will actually work out. I think the advice you got in #clojure to
 use zippers is probably correct. Here's a sketch I bashed out that
 seems to do roughly what you want:https://gist.github.com/1807340(I
 took the liberty of wrapping the whole thing in another [] under the
 assumption you'd want to record multiple top-level calls; if not you
 can just call first on the result).

 On Feb 11, 8:39 pm, jweiss jeffrey.m.we...@gmail.com wrote:







  I've been working on a tracing library, that works much like
  clojure.contrib.trace (based on it, actually).   One sticky problem
  I've found is, hierarchical logs are really crappy to try to stream to
  a file.  You can't just keep writing to the end of the file - new data
  needs to be inserted before existing end-tags.  So what I'm doing is
  storing the data as a list, until I know the data is complete, and
  then i turn it back into a tree to write the file.

  However I can't think of a simple way to do it, even though it seems
  like a simple operation.

  I want to turn this list of pairs (first item is the fn call or return
  value, the second is a truthy value marking whether it's a call or
  return)

  '[[(+ 1 (- 5 2) nil]
   [(- 5 2) nil]
   [3 true]
   [4 true]]

  I want to turn that into
  [(+ 1 (- 5 2))
      [(- 5 2)
       3]
   4]

  Is there a simple way to do this?

-- 
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: Hierarchical logs

2012-02-14 Thread jweiss
It occurred to me that ultimately what I want is just a pretty-printed
output that I can put on a webpage and apply syntaxhighlighter to.

I should be able to use a custom pprint dispatch to take this
[[(+ 5 (- 4 2 (* 9 3)) (* 5 (+ 6 3))) nil]
 [(- 4 2 (* 9 3)) nil]
 [(* 9 3) nil]
 [27 true]
 [-25 true]
 [(* 5 (+ 6 3)) nil]
 [(+ 6 3) nil]
 [9 true]
 [45 true]
 [25 true]]

and print something like this:

(+ 5 (- 4 2 (* 9 3)) (* 5 (+ 6 3)))
  (- 4 2 (* 9 3))
(* 9 3)
27
  -25
  (* 5 (+ 6 3))
(+ 6 3)
9
  45
25

Without even converting it into a tree.  But I am having a hard time
finding an example of custom dispatch, or docs on how to write one.  I
really just want things printed the same as pprint currently does, but
being able to specify extra indent for the whole block.  I had
originally planned to output html where each item was properly nested
as html divs, but I think that is getting overly complex.

-jeff

On Feb 14, 10:14 am, jweiss jeffrey.m.we...@gmail.com wrote:
 Thanks, Alan,

 The solution I used looks exactly like yours:

 (defn mktree [vz [i out?]]
   (if out?
     (- vz (zip/append-child i) zip/up )
     (- vz (zip/append-child [i]) zip/down zip/rightmost)))

 (defn as-tree [tracelist]
   (zip/root (reduce mktree (zip/vector-zip []) tracelist)))

 Thinking about it some more, I don't think I'm going to come up with a
 solution that's any more efficient or easy to code as this one.  The
 real work is figuring out where the next element needs to be
 inserted.  Zipper keeps that information as part of the data structure
 so it doesn't have to be re-calculated every iteration.  My previous
 solution using loop had kept an accumulator (a list of indices to pass
 to assoc-in).

 -jeff

 On Feb 12, 3:42 am, Alan Malloy a...@malloys.org wrote:







  I toyed with some simple ways of doing this, but I don't think any of
  them will actually work out. I think the advice you got in #clojure to
  use zippers is probably correct. Here's a sketch I bashed out that
  seems to do roughly what you want:https://gist.github.com/1807340(I
  took the liberty of wrapping the whole thing in another [] under the
  assumption you'd want to record multiple top-level calls; if not you
  can just call first on the result).

  On Feb 11, 8:39 pm, jweiss jeffrey.m.we...@gmail.com wrote:

   I've been working on a tracing library, that works much like
   clojure.contrib.trace (based on it, actually).   One sticky problem
   I've found is, hierarchical logs are really crappy to try to stream to
   a file.  You can't just keep writing to the end of the file - new data
   needs to be inserted before existing end-tags.  So what I'm doing is
   storing the data as a list, until I know the data is complete, and
   then i turn it back into a tree to write the file.

   However I can't think of a simple way to do it, even though it seems
   like a simple operation.

   I want to turn this list of pairs (first item is the fn call or return
   value, the second is a truthy value marking whether it's a call or
   return)

   '[[(+ 1 (- 5 2) nil]
    [(- 5 2) nil]
    [3 true]
    [4 true]]

   I want to turn that into
   [(+ 1 (- 5 2))
       [(- 5 2)
        3]
    4]

   Is there a simple way to do this?

-- 
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


Hierarchical logs

2012-02-11 Thread jweiss
I've been working on a tracing library, that works much like
clojure.contrib.trace (based on it, actually).   One sticky problem
I've found is, hierarchical logs are really crappy to try to stream to
a file.  You can't just keep writing to the end of the file - new data
needs to be inserted before existing end-tags.  So what I'm doing is
storing the data as a list, until I know the data is complete, and
then i turn it back into a tree to write the file.

However I can't think of a simple way to do it, even though it seems
like a simple operation.

I want to turn this list of pairs (first item is the fn call or return
value, the second is a truthy value marking whether it's a call or
return)

'[[(+ 1 (- 5 2) nil]
 [(- 5 2) nil]
 [3 true]
 [4 true]]

I want to turn that into
[(+ 1 (- 5 2))
[(- 5 2)
 3]
 4]

Is there a simple way to do this?

-- 
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: clojure.contrib.prxml broken in Clojure 1.3.0

2012-01-18 Thread jweiss
It might not make a lot of practical difference, but my understanding
is that CDATA isn't parsed as XML, so if you have a lot of non-xml
data, it's probably better to use CDATA so that it is not parsed when
it's read back in.

On Jan 17, 11:12 pm, Alan Malloy a...@malloys.org wrote:
 It doesn't need CDATA - data.xml just automatically escapes XML
 special-characters if it sees them.

 On Jan 17, 4:12 pm, jweiss jeffrey.m.we...@gmail.com wrote:







  By the way, the reason I stuck with prxml is its handling of CDATA,
  which as far as I know, the newer lib doesn't do yet.

  On Jan 17, 8:10 am, cassiel n...@cassiel.com wrote:

   This is straight from the doc string:

   (with-out-str (p/prxml [:p {:class greet} [:i Ladies 
   gentlemen]]))

   Works in Clojure 1.2.1:

   (:ok \p class=\\\greet\\\iLadies amp; gentlemen/i/p\)

   (that's pasted from the slime event buffer, hence the superfluous
   armour.)

   Fails in Clojure 1.3.0:

   clojure.lang.Numbers.lt(II)Z
     [Thrown class java.lang.NoSuchMethodError]

   Is prxml still being supported? If not, is there a better Clojure-DSL-
   to-XML package?

-- 
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: clojure.contrib.prxml broken in Clojure 1.3.0

2012-01-17 Thread jweiss
I fixed up clojure.contrib.prxml to work with 1.3, at least it's
working fine for me.  You can get the jar from clojars with

[weissjeffm/clojure.prxml 1.3.0-SNAPSHOT]

source is here:
https://github.com/weissjeffm/clojure.prxml


On Jan 17, 8:10 am, cassiel n...@cassiel.com wrote:
 This is straight from the doc string:

 (with-out-str (p/prxml [:p {:class greet} [:i Ladies 
 gentlemen]]))

 Works in Clojure 1.2.1:

 (:ok \p class=\\\greet\\\iLadies amp; gentlemen/i/p\)

 (that's pasted from the slime event buffer, hence the superfluous
 armour.)

 Fails in Clojure 1.3.0:

 clojure.lang.Numbers.lt(II)Z
   [Thrown class java.lang.NoSuchMethodError]

 Is prxml still being supported? If not, is there a better Clojure-DSL-
 to-XML package?

-- 
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: clojure.contrib.prxml broken in Clojure 1.3.0

2012-01-17 Thread jweiss
By the way, the reason I stuck with prxml is its handling of CDATA,
which as far as I know, the newer lib doesn't do yet.

On Jan 17, 8:10 am, cassiel n...@cassiel.com wrote:
 This is straight from the doc string:

 (with-out-str (p/prxml [:p {:class greet} [:i Ladies 
 gentlemen]]))

 Works in Clojure 1.2.1:

 (:ok \p class=\\\greet\\\iLadies amp; gentlemen/i/p\)

 (that's pasted from the slime event buffer, hence the superfluous
 armour.)

 Fails in Clojure 1.3.0:

 clojure.lang.Numbers.lt(II)Z
   [Thrown class java.lang.NoSuchMethodError]

 Is prxml still being supported? If not, is there a better Clojure-DSL-
 to-XML package?

-- 
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: Really loving Clooj but..

2011-12-31 Thread jweiss
I use a modified version of tools.trace (or rather the old version
called clojure.contrib.trace, but works with 1.3), you might be
interested in some of the additions (sorry not well doc'd at the
moment):

1) Don't blow up if a function throws an exception (return value shown
in the trace will be the exception object).
2) option to trace a multi-threaded app - output is to a separate file
for each thread
3) Trace entire namespaces, multiple namespaces, exclude fn's from
traced namespaces.
4) ability to pretty print the trace to html with syntax highlighter.

1 3 are probably the only ones useful at the repl.

Jeff
https://github.com/weissjeffm/fn.trace/

On Dec 30, 11:52 am, Erlis Vidal er...@erlisvidal.com wrote:
 Hi Jonas,

 That's what I was looking for. Thanks for your reply







 On Fri, Dec 30, 2011 at 8:16 AM, Jonas jonas.enl...@gmail.com wrote:
  You should take a look at tools.trace [1]. A minimal example:

      (ns trc.core
        (:use [clojure.tools.trace :only [deftrace]]))

      (deftrace fib [n]
        (if (or (= n 0) (= n 1))
          1
         (+ (fib (- n 1)) (fib (- n 2)

  the following is printed when (fib 4) is evaluated:

  TRACE t2302: (fib 4)
  TRACE t2303: | (fib 3)
  TRACE t2304: | | (fib 2)
  TRACE t2305: | | | (fib 1)
  TRACE t2305: | | | = 1
  TRACE t2306: | | | (fib 0)
  TRACE t2306: | | | = 1
  TRACE t2304: | | = 2
  TRACE t2307: | | (fib 1)
  TRACE t2307: | | = 1
  TRACE t2303: | = 3
  TRACE t2308: | (fib 2)
  TRACE t2309: | | (fib 1)
  TRACE t2309: | | = 1
  TRACE t2310: | | (fib 0)
  TRACE t2310: | | = 1
  TRACE t2308: | = 2
  TRACE t2302: = 5

  [1]:https://github.com/clojure/tools.trace

   --
  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

-- 
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: Could be my favourite improvement in 1.4

2011-12-20 Thread jweiss
Even if they did, it's pretty easy to surround the paste with (read-
json ... ).

On Dec 20, 10:36 am, Alex Baranosky alexander.barano...@gmail.com
wrote:
 For what it's worth, I think colon's as whitespace in maps adds confusion,
 without, imo adding a ton of power or readability.  In terms of power, it
 gives you the ability to paste JSON into a Clojure REPL; I wonder how often
 that use case comes up?  In terms of readability, any benefit it gives you
 in readability would be counterweighted by the additional syntax rules it
 adds.

 The only way I could see this as worth it, would be if people wanted to
 paste 'foreign' map data into a Clojure REPL a ton more frequently than I
 imagine they do.

 Alex

-- 
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


Concurrency design

2011-08-08 Thread jweiss
I'm having some trouble figuring out what clojure concurrency tools I
can use to solve my problem.

The application I'm trying to build is a functional test harness, like
TestNG but for clojure.  It takes an input a tree of tests to run
(where child tests don't run unless the parent passed), and runs the
tests in parallel (as much as possible) on a fixed number of threads.
Each tree node contains a promise, where the test results are placed.
A report runs at the end, and naturally blocks until all the promises
are delivered.

The problem comes where some kinds of testing require some per-thread
setup/teardown.  For instance, selenium opens a browser and drives it
to run tests.  Obviously you can't have multiple tests running in the
same browser at the same time.  So you need multiple browsers being
driven by one thread each.  Each thread has to rebind the selenium
client var to a new value.

So to sum up, I need a thread pool, and thread-local bindings so that
clients like selenium can run multithreaded.
java.util.concurrent.Executors fail because I can't get thread-local
bindings.  I haven't been able to find a way to run the entire worker
thread with a (binding ...) form, that would apparently involve
changing the implementation of the java lib, and too much of that
stuff is marked private to proxy it.

Agents seemed like a possibility (just for use as a thread pool), but
my use-case does not seem to match.  I have a single work queue, not
many.  And the agents value would have to be the local bindings, which
would never change.  And agents don't have any way of reporting if
they are busy or not, so they'd have to pull in their work rather than
having it sent to them.  My app seems like it would be a rather gross
abuse of agents.

Futures don't work because I need to limit the number of threads, I
can't have 500 browsers open at once.

Can someone suggest a direction I should go?

Thanks,

Jeff

-- 
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: Concurrency design

2011-08-08 Thread jweiss
If I may reply to myself:

Sometimes just stating the problem for someone else makes the solution
clear.

My false assumption was that I needed something as fancy as agents or
ThreadPoolExecutor.

The solution was simple Just queue up the tests with a BlockingQueue,
start some plain java threads with a consume fn.  The consume fn
does the binding, polls the queue and exits when a done flag is
set.  The done flag is set to true when the report finishes.

Jeff

On Aug 8, 12:59 pm, jweiss jeffrey.m.we...@gmail.com wrote:
 I'm having some trouble figuring out what clojure concurrency tools I
 can use to solve my problem.

 The application I'm trying to build is a functional test harness, like
 TestNG but for clojure.  It takes an input a tree of tests to run
 (where child tests don't run unless the parent passed), and runs the
 tests in parallel (as much as possible) on a fixed number of threads.
 Each tree node contains a promise, where the test results are placed.
 A report runs at the end, and naturally blocks until all the promises
 are delivered.

 The problem comes where some kinds of testing require some per-thread
 setup/teardown.  For instance, selenium opens a browser and drives it
 to run tests.  Obviously you can't have multiple tests running in the
 same browser at the same time.  So you need multiple browsers being
 driven by one thread each.  Each thread has to rebind the selenium
 client var to a new value.

 So to sum up, I need a thread pool, and thread-local bindings so that
 clients like selenium can run multithreaded.
 java.util.concurrent.Executors fail because I can't get thread-local
 bindings.  I haven't been able to find a way to run the entire worker
 thread with a (binding ...) form, that would apparently involve
 changing the implementation of the java lib, and too much of that
 stuff is marked private to proxy it.

 Agents seemed like a possibility (just for use as a thread pool), but
 my use-case does not seem to match.  I have a single work queue, not
 many.  And the agents value would have to be the local bindings, which
 would never change.  And agents don't have any way of reporting if
 they are busy or not, so they'd have to pull in their work rather than
 having it sent to them.  My app seems like it would be a rather gross
 abuse of agents.

 Futures don't work because I need to limit the number of threads, I
 can't have 500 browsers open at once.

 Can someone suggest a direction I should go?

 Thanks,

 Jeff

-- 
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: Concurrency design

2011-08-08 Thread jweiss
Ken,

Thanks for your response!  Those are some great suggestions.  Some
look quite promising, a few don't fit my purposes.  For instance, I
can't use pcalls because the user needs to be able to control the
number of threads.  Your method to skip tests using 'and' works, and
is interesting, but I want the tree of tests to be easily printable
and for users to be able to write them that way (nested map/vector),
so that dependencies are visible at a glance without skipping around
in the code.

Part of the reason I embarked on this project was that midje, lazytest
etc are used almost exclusively for unit testing.  I need to do black
box testing, where the app being tested is remote and it is only
accessible via HTTP or some other network protocol.

Some of the features I wanted are:

* Self-documenting tests.  There should be no need to write english
testcases AND automate them, the automation IS the testcase.
However, management likes to know that tests can be read and run by
someone besides the person who wrote them, even when they are
automated.  So I want

(defn duplicate-name-disallowed-test []
  (let [name testitem]
   (create-widget name)
   (expect NameTakenError
(create-widget name)))

to be the canonical testcase.  If necessary I can process the form
into more human readable text (although to me it's plenty readable
already, but non programmers might disagree). Unfortunately automating
a testcase doesn't absolve it from being in the testcase tracking db.

* Self-logging (I use clojure.contrib.trace with some modification -
writing log4j statements is a waste of time IMO). Automated tests are
software, and so is the app under test.  The automation simply flags
when it doesn't get what it expects.  The engineer's job is to figure
out which software is wrong, so logs are important.
* Fast execution (hence multithreaded) - the more often tests can run,
the fewer suspects you have for the cause of the breakage.
* Ability to control depth of testing (this is why I used a tree
structure where dependent tests are children - it forces the automator
to lay out tests such that the most severe bugs are found first. If
you can't log in, the whole app is broken, so login test goes at the
root of the tree.  In most cases, bug severity = depth in tree.
Quick testing means maxdepth = 2 or 3, detailed testing means maxdepth
= unlimited).


On Aug 8, 2:12 pm, Ken Wesson kwess...@gmail.com wrote:
 If the local bindings will never change, then why not just use
 (binding [whatever-setup ...] ...) wrapping the individual test bodies
 that need such setup? (Where explicit tear-down is required, you'd
 need try ... finally as well, or better yet a macro like with-open,
 but using binding instead of let, to abstract out the repeated aspects
 of such code. Common setups could become more macros, e.g.
 (with-foo-whatsit [some-symbol some-other-symbol] ...).)

 If the bindings are to stateful stuff that a sequence of tests will
 alter, though, you have more problems. Possible improvements:

 * Redesign the whole thing to be more functional and less stateful.

 * At least, move as much into pure functions as possible; the pure
 functions are easy to test.

 * The (remaining) sequences of tests on state will have to run
 sequentially, so combine them into a single test that calls the
 smaller ones.

 You'll end up with something like:

 (def results (atom {}))

 (def tests (atom []))

 (def foo nil)

 (def bar nil)

 (defmacro deftest ... )

 (deftest foo nil
   [foo (initialize-some-resource)
    bar (initialize-another)]
     (the test goes here)))

 and that produces something like

 (do
   (defn foo []
     (binding [foo (initialize-some-resource)]
       (try
         (binding [bar (initialize-another)]
           (try
             (deliver (@results foo) (the test goes here))
             (finally (.close bar
         (catch Throwable _ (deliver (@results foo) false))
         (finally (.close foo)
   (swap! results assoc foo (promise))
   (swap! tests conj foo))

 whereas

 (deftest bar foo ...)

 is similar, but with foo instead of nil for the second argument the
 bar function body gets wrapped in:

 (if @(@results foo)
   (do
     (body that would have been)
     (with nil second arg))
   (deliver (@results bar) false))

 so when bar is run it blocks until foo has run, and short-circuits to
 failing if foo failed, but runs if foo succeeded.

 And then there'd be

 (deftest baz :subtest ...)

 which expands without swap!s or a wrapper -- it just becomes a
 function like foo and nothing else. A later test body can do setup,
 call baz as a function along with several other subtests, and do
 teardown, e.g.

 (deftest quux ...
   ...
   (and (baz) (baz2) (baz3)))

 which, obviously, short-circuits to failure if any of these fails and
 otherwise runs them all and returns baz3's result.

 Lastly, you'd have

 (doall (apply pcalls @tests))

 to run the tests and

 (report)

 after that, with

 (defn report
   (doseq 

Re: Anyone on Google+ yet?

2011-07-17 Thread jweiss
http://gplus.to/weissjeffm

-- 
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: Anyone on Google+ yet?

2011-07-17 Thread jweiss
This does bring up an interesting flaw in G+.  If I add Clojure people
who I don't know personally, how will they know to add me to a Clojure
circle?  G+ (rightfully) doesn't automatically tell them what circle I
added them to.  It doesn't appear to be optional to tell them, either.

On Jul 14, 7:56 pm, Kyle Root k...@kylert.com wrote:
 gplus.to/Kylert







 On Thu, Jul 14, 2011 at 7:00 PM, ianp ian.phill...@gmail.com wrote:
  Ian

  Looks like G+ is pretty popular with the Clojure crowd :-)

  --
  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

-- 
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: another question on macros defining functions

2011-06-04 Thread jweiss
If you are connected to a swank server, have you tried C-c C-k to
compile the file you're editing?


On Jun 4, 1:15 am, nil ache...@gmail.com wrote:
 Mark, it turns out that everything I need is known and static at hack-
 time. (Sorry for making it sound otherwise) I know all the names,
 values, *and* behaviors that I want to use when I'm writing the code
 for my tests. I just want my clojurebox symbol completion to work
 after having written a bunch of one-liners to declare families of
 functions. I think it forces me to eval certain files before I edit
 others. Am I making you all cringe?

-- 
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: another question on macros defining functions

2011-06-03 Thread jweiss
As Ken said, you have to remember macros expand at compile time.
Think of a macro call as folded up code that the compiler unfolds
for you.  A macro saves you from writing repetitive code.

But if you are trying to define a function whose name isn't known
until runtime, that's a whole different thing.  Doesn't really make
sense to me, since the reason you want to define a var for your fn is
presumably because you have code elsewhere that calls it.  But if both
the definition and call to the fn aren't known until runtime, I don't
see the need for a var. Perhaps you could just use a map of names
(either strings or keywords or even symbols) to anonymous fn's?  At
runtime you can add fns to the map, and later pick the fn and call it?

(def fns (atom {})

(defn add-fn [name f]
  (swap! fns assoc name f))

(defn call-fn [name]
  ((@fns name)))

something like that.  No macros needed.

On Jun 2, 10:34 pm, Ken Wesson kwess...@gmail.com wrote:
 On Thu, Jun 2, 2011 at 10:06 PM, nil ache...@gmail.com wrote:
  Hi

  Here's another macro-noob question. (Thanks for the help on the
  previous question and please do let me know if stackoverflow is a more
  appropriate place to ask noob questions.)

  I'm trying to write a macro (or a function) that defines/declares
  specifically named functions. In (let [eff gee] (foo eff)) I want
  the macro foo to define/declare a function called foo-gee, not foo-
  eff. What should I do differently?

 The problem here is that macros run at compile time, but let bindings
 exist at run time.

 If you need the name to be determined at run time you will need to use eval.

 If you don't need the name at run time, why are you using (let [eff
 gee] (foo eff)) and not simply (foo gee)?

 Please state your requirements clearly.
 --
 Protege: What is this seething mass of parentheses?!
 Master: Your father's Lisp REPL. This is the language of a true
 hacker. Not as clumsy or random as C++; a language for a more
 civilized age.

-- 
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: macro says Can't use qualified name as parameter

2011-05-28 Thread jweiss


On May 27, 1:46 pm, nil ache...@gmail.com wrote:
 I was looking 
 athttp://saucelabs.com/blog/index.php/2009/12/running-your-selenium-tes...
 and in the comments, :Scott suggested that a macro could reduce some
 of the boilerplate that you see here:

 (def test-google
   {
    :name google
    :test (fn [client]
            (doto client
              (.open http://www.google.com;)
              (.type q Sauce Labs)
              (.click btnG)
              (.waitForPageToLoad 5000))
            (.isTextPresent client Selenium))})

 (def test-yahoo
   {
    :name yahoo
    :test (fn [client]
            (doto client
              (.open http://yahoo.com;)
              (.type p Sauce Labs)
              (.click search-submit)
              (.waitForPageToLoad 5000))
            (.isTextPresent client Selenium))})

 You can see the boilerplate of defining the map, typing the names of
 the two keys, calling the thing test-name ... So I tried writing a
 macro for this. But when I use my first attempt, it says Can't use
 qualified name as parameter. Here's my first attempt:

 (defmacro deftest [name  body]
   (let [test-n (symbol (str test- name))
         n (str name)]
     `(def ~test-n
           {:name ~n
            :test (fn [client]
                    ~@body)})))

 The macro expansion of the following looks good, but actually running
 it yields the complaint mentioned above:

   (deftest google
     (doto client
       (.open http://www.google.com;)
       (.type q Sauce Labs)
       (.click btnG)
       (.waitForPageToLoad 5000))
     (.isTextPresent client Selenium))

 My second attempt works ..

 (defmacro deftest [name client  body]
   (let [test-n (symbol (str test- name))
         n (str name)]
     `(def ~test-n
           {:name ~n
            :test (fn [~client]
                    ~@body)})))

 ... but now the user has to mention the client twice:

   (deftest google client
     (doto client
       (.open http://www.google.com;)
       (.type q Sauce Labs)
       (.click btnG)
       (.waitForPageToLoad 5000))
     (.isTextPresent client Selenium))

 How do I get around this?

I think what others are getting at is that you shouldn't have the
macro define the 'frame' of the (fn ...) form.  Just pass it in whole
in your macro call like

(deftest google
   (fn [client]
  (doto client
  (.open http://www.google.com;)
  (.type q Sauce Labs)
  (.click btnG)
  (.waitForPageToLoad 5000))
(.isTextPresent client Selenium)))

It is a bit more boilerplate but you're less likely to shoot yourself
in the foot.  One thing i've done in macros, (and I don't know how
advisable or good clojure this is), but, *if* you're sure all your
(fn...) forms you pass in will be explicit fn forms, and not just the
symbol of an existing function, you can extract the parameter name and
use it as your name field.

In the macro you'd do something like (- (second body) first name),
which would return the string client.
It's probably not the best idea since it *would* prevent you from
passing in symbols of existing functions, rather than (fn ...)
forms.

I'm not sure if you really require vars defined for each test, or if
you can just put them in a single map like so:

(def tests {:google (fn [client] ...)
:yahoo (fn [client] ...)})

and then it'd be easy to process that map:

(defn generate [m]
  (zipmap (keys m) (for [[k v] m] {:name (name k) :test v})))

and finally

(run-tests (generate tests))


HTH,
Jeff

-- 
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: macro says Can't use qualified name as parameter

2011-05-28 Thread jweiss
Oops, ignore the part about extracting the parameter name from the fn
form.  I meant to delete that part, I misunderstood your problem at
first.

I say just use functions - you don't need macros here.  The
boilerplate of typing (fn [client]   multiple times is not enough to
justify their use, IMO.

Jeff




On May 28, 2:04 pm, jweiss jeffrey.m.we...@gmail.com wrote:
 On May 27, 1:46 pm, nil ache...@gmail.com wrote:









  I was looking 
  athttp://saucelabs.com/blog/index.php/2009/12/running-your-selenium-tes...
  and in the comments, :Scott suggested that a macro could reduce some
  of the boilerplate that you see here:

  (def test-google
    {
     :name google
     :test (fn [client]
             (doto client
               (.open http://www.google.com;)
               (.type q Sauce Labs)
               (.click btnG)
               (.waitForPageToLoad 5000))
             (.isTextPresent client Selenium))})

  (def test-yahoo
    {
     :name yahoo
     :test (fn [client]
             (doto client
               (.open http://yahoo.com;)
               (.type p Sauce Labs)
               (.click search-submit)
               (.waitForPageToLoad 5000))
             (.isTextPresent client Selenium))})

  You can see the boilerplate of defining the map, typing the names of
  the two keys, calling the thing test-name ... So I tried writing a
  macro for this. But when I use my first attempt, it says Can't use
  qualified name as parameter. Here's my first attempt:

  (defmacro deftest [name  body]
    (let [test-n (symbol (str test- name))
          n (str name)]
      `(def ~test-n
            {:name ~n
             :test (fn [client]
                     ~@body)})))

  The macro expansion of the following looks good, but actually running
  it yields the complaint mentioned above:

    (deftest google
      (doto client
        (.open http://www.google.com;)
        (.type q Sauce Labs)
        (.click btnG)
        (.waitForPageToLoad 5000))
      (.isTextPresent client Selenium))

  My second attempt works ..

  (defmacro deftest [name client  body]
    (let [test-n (symbol (str test- name))
          n (str name)]
      `(def ~test-n
            {:name ~n
             :test (fn [~client]
                     ~@body)})))

  ... but now the user has to mention the client twice:

    (deftest google client
      (doto client
        (.open http://www.google.com;)
        (.type q Sauce Labs)
        (.click btnG)
        (.waitForPageToLoad 5000))
      (.isTextPresent client Selenium))

  How do I get around this?

 I think what others are getting at is that you shouldn't have the
 macro define the 'frame' of the (fn ...) form.  Just pass it in whole
 in your macro call like

 (deftest google
    (fn [client]
       (doto client
       (.open http://www.google.com;)
       (.type q Sauce Labs)
       (.click btnG)
       (.waitForPageToLoad 5000))
     (.isTextPresent client Selenium)))

 It is a bit more boilerplate but you're less likely to shoot yourself
 in the foot.  One thing i've done in macros, (and I don't know how
 advisable or good clojure this is), but, *if* you're sure all your
 (fn...) forms you pass in will be explicit fn forms, and not just the
 symbol of an existing function, you can extract the parameter name and
 use it as your name field.

 In the macro you'd do something like (- (second body) first name),
 which would return the string client.
 It's probably not the best idea since it *would* prevent you from
 passing in symbols of existing functions, rather than (fn ...)
 forms.

 I'm not sure if you really require vars defined for each test, or if
 you can just put them in a single map like so:

 (def tests {:google (fn [client] ...)
             :yahoo (fn [client] ...)})

 and then it'd be easy to process that map:

 (defn generate [m]
   (zipmap (keys m) (for [[k v] m] {:name (name k) :test v})))

 and finally

 (run-tests (generate tests))

 HTH,
 Jeff

-- 
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: Weening myself off of global state - what's the idiomatic way to solve this?

2011-04-14 Thread jweiss
I'd start by making functions that take arguments.  For instance (defn
draw-ball [ball] ...)


On Apr 13, 1:22 pm, Brandon Ferguson bnfergu...@gmail.com wrote:
 I'm not sure if this is the place to ask this but I've been struggling
 with a few things in the world of Clojure. I've been using Processing
 to learn Clojure (since I'm somewhat familiar with Processing) but the
 tough part has been dealing with things like x, y positions of objects
 without keeping some global state (I'm not sure if it's even
 possible).

 The code in question is:https://gist.github.com/887256

 All this does is bounce a ball around a screen, for every frame
 Processing calls draw which moves the ball one frame. Since I'm not
 the one driving the loop I ended up using atoms to update some bits of
 global state but that feels really dirty.

 If I could drive the frames it would be easy to use recur or some
 other bit of state passing as I render each successive frame. I've
 considered using sequences and passing a frame number (which would be
 stored in a global as well) in but then it'd (I assume) have to run
 through every number up to that the one I passed it. Seems like
 performance would degrade the longer it ran. There's also this idea
 rattling around in my head where I'd just rewrite the function
 everytime with the new state - but seems like you couldn't scale that
 to multiple balls bouncing around (which is the next step) - and God
 knows what, if any, performance implications that would have.

 So I'm not sure where that leaves me - learning functional stuff can
 be wonderfully mind breaking but sometimes I feel like I don't even
 have the tools in my head to work some things out. Is there some
 technique I'm missing for dealing with state between successive calls
 of a function?

 How would you solve something like this?
 -Brandon

-- 
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: Weird nested macro problem

2011-02-01 Thread jweiss
If I remember right from looking at clojure.contrib.condition's source
(which I did because I wrote a similar error handling lib, which has a
few extra features but isn't ready for prime time)...

handle doesn't actually exist as a function or macro.  It doesn't
expand - the handler-case macro looks for it and basically drops the
symbol handle and uses the rest of the form to create a function.  I
would think the unquote-quote should leave handle unqualified and do
the right thing, but apparently not.

https://github.com/richhickey/clojure-contrib/blob/ec6a7579d6b1c0bfa42e3666cfad196cffc966fe/src/main/clojure/clojure/contrib/condition.clj#L71

I believe somehow the (= 'handle (first %)) comparison on line 92 is
returning false on your handle form.  I am not sure why.  But that
might be worth exploring at the repl.

Jeff

On Feb 1, 4:09 pm, Straszheim, Jeff jstra...@akamai.com wrote:
 So, I have a macro that looks something like this:

 (defmacro test-failure
   [ forms]
   `(handler-case :type
      ~@forms
      (~'handle :error/error
        (println error happened

 (My real macro is more complex, but this gives the idea.)

 If I eval

  (test-failure (println test))

 I get:

  = Unable to resolve symbol: handle in this context

 However, if I macroexpand-1 the thing, I get:

  (macroexpand-1 '(test-failure (println test)))

  = (clojure.contrib.condition/handler-case :type (println test) (handle 
 :error/error (clojure.core/println error happened)))

 That is correct, and if I eval just that it works fine.

 Here is an interesting thing:  if I do this:

  (macroexpand '(test-failure (println test)))

 I get

  = (try (println test) (handle :error/error (clojure.core/println error 
 happened)) (catch clojure.contrib.condition.Condition c__19__auto__ 
 (clojure.core/binding [clojure.contrib.condition/*condition-object* 
 c__19__auto__ clojure.contrib.condition/*condition* (clojure.core/meta 
 c__19__auto__) clojure.contrib.condition/*selector* (:type (clojure.core/meta 
 c__19__auto__))] (clojure.core/cond :else 
 (clojure.contrib.condition/raise)

 It's expanded the handler-case part, but the handle is still there.  That 
 seems wrong to me.

 I've tried lots of different ways to specify handle besides ~'handle, but 
 they all seem to fail.

 Any suggestions?

-- 
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


Error handling implementation - looking for criticisms and suggestions

2010-12-17 Thread jweiss
I'd been shopping around for an error handling kit for Clojure.  What
I needed was:

* The ability to specify error handlers at the caller's level, that
are accessible all the way up the stack from them.
* Ability to include more data in an error than just a message and
stack trace.  That data should be accessible to handlers.
* The ability to specify pre-defined methods of recovering from an
error, at any point on the stack between the caller and the origin of
the error.  The caller can select the recovery method by name.
* Ability to handle errors by type, in a hierarchical fashion, similar
to java's catch.
* Compatibility with java exceptions.
* Ability to nest hander forms
* No AOT compilation if I can help it.

Chouser's error-kit offers this, but Chouser himself told me I
probably shouldn't use it unless I needed all the features, like
continue-with.  I didn't need continue-with, and I figure if the
author warns you away from a lib, probably best to listen :)

I also took a look at clojure.contrib.condition, but it doesn't allow
you to specify pre-defined recoveries, and requires AOT compilation.

So I took a stab at it myself:  https://gist.github.com/745223

It's not polished at all yet - please don't use it for anything
important!  I wanted to see if you all had any suggestions or
criticisms before I went any further.  Changes to the gist are most
welcome :)

Some notes:

* Uses javax.naming.NamingException internally - because it is an
existing exception class that has a getter/setter that takes Object.
This is just a hack to store clojure types in the exception and have
them travel down the stack.  I wanted to avoid adding my own java
exception class like clojure.contrib.condition had to do.  I could
still do that without a lot of changes.
* Makes use of 'binding' internally to store handlers.  That allows
nested with-handler forms.
* Adding recoveries to a java exception is not working, but it should
be a simple fix once i track down the problem.

Jeff

-- 
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: parameters destructuring sets?

2010-12-05 Thread jweiss


On Dec 5, 2:10 pm, Alex Ott alex...@gmail.com wrote:
 Re

 jweiss  at Sun, 5 Dec 2010 10:29:41 -0800 (PST) wrote:
  j I'm no expert on this, but i'll take a crack at it.

  j I think it's because sets don't (necessarily) impose any order, so
  j there's no concept of first or nth.  So destructuring would
  j essentially be assigning a random item to x, or for join, joining them
  j in random order.

 Sometimes, order doesn't matter, for example, I want to print data from set
 (or any collection that is transformable into sequence), using some
 separator between elements...

 For some operations we can't also predict order, for example, conj behaves
 differently for lists and vectors

 --
 With best wishes, Alex Ott, MBAhttp://alexott.blogspot.com/       
 http://alexott.net/http://alexott-ru.blogspot.com/
 Skype: alex.ott

If you wanted to, for example, print a set with separators in between,
would you need to use destructuring?

I'd just do (apply str (interpose , #{:a :b :c})
- :a,:b,:c

I don't think conj adding to the front for lists and the end for
vectors is unpredictable at all.  I know that

(conj '(1 2) 3))
- (3 1 2)

and

(conj [1 2] 3)
- [1 2 3]

before I even type it on a REPL.  That's totally different than nth
for a set being undefined.  It's undefined on purpose.

Now, if you are using a sorted-set, then you have a point there, I
would expect that nth means something then.  But yeah, clojure doesn't
let you call nth on it directly, you have to make a seq out of it
first.  Not sure what the performance implication is there, but it's
not much effort to write:

(nth (sequ­ence (sort­ed-set 1 3 2)) 2)
- 3

I will let people who are more knowledgeable comment on why there's no
nth on a sorted-set.

-- 
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