Re: making code readable

2008-12-31 Thread Daniel Eklund

 This is the excuse continually trotted out by people too lazy to
 comment, or who think themselves superior to merely mortal programmers
 who have to work in teams and actually communicate with people.
 Redundancy in communication is almost never redundant; think of it as
 a checksum. snip

A checksum should be trusted.  Comments sometimes cannot.

Since you brought up the issue with working in teams, I will submit my
decade and a half of experience coding in 'enterprise' team
environments (my chosen hell).  I have built upon and maintained Java
code that has grown through accretion of various consulting
organizations, and I never trust comments.  Even with third party
(supposedly stable) APIs, I have had  (more than once) to open up the
code to discover that the javadocs are out of date and incorrect.  I
do my bit; I try to maintain my comments, but I never trust.  The code
IS the answer, always.


 'Redundant comments are useless' is the mantra of the dilettante, the
 amateur, and the cowboy.

I believe the मन्त्र 'comments are useless'  is more cowboy-like, not
'redundant comments are useless'.  If not, what about the phrase
'useless comments are useless'?
--~--~-~--~~~---~--~~
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
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: Understanding how to use namespaces

2008-12-30 Thread Daniel Eklund

Hey Mark,

In addition to Meikel's explanation above,  have a look at this
message

http://groups.google.com/group/clojure/msg/17ada41fcb5ef667

from the overall thread

http://groups.google.com/group/clojure/browse_frm/thread/ff80d120c996ba1a/9bfbfe1b08246035#

This was the post that finally made it clear (for me) the differences
between use, require, refer, load etc Namespaces and library
loading are intertwined.

daniel
--~--~-~--~~~---~--~~
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
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: Stumped - Java hangs when using Swing in Slime

2008-12-19 Thread Daniel Eklund

 Anyone have any ideas? I'm pretty confused as to what might be going
 on. Some sort of deadlock in the thread pool that isn't allowing the
 AWT event thread any cycles? I'm looking at the thread pool in JSwat
 and I see a lot of Swank threads, but I can't tell exactly what's
 going on.

I literally just had this problem today.  I was having slime hang on
me with _any_ swing code.  So I tried the basic repl and even the most
basic

(. javax.swing.JOptionPane (showMessageDialog nil Hello World))

and even this was failing.  Spent an hour svn updating, etc.

Finally, I clicked on the system icon tray at the bottom right of XP
and noticed that that the stupid Java download manager wanted me to
update.  I let it download whatever patch it wanted and then suddenly
everything worked.

It could be coincidental.  But I am telling you just in case.

--~--~-~--~~~---~--~~
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
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: FAQ

2008-12-18 Thread Daniel Eklund

 Suggestions for entries welcome here.

 Rich

How about:

What language constructs/objects may be found in the function position
of an expression?

Ii like the fact that sets, maps and vectors are all 'functions of
their keys',  and that keywords and symbols are functions of maps.

((([ + - apply ] 2) hash-map  [ 1 one 3 three])   1 )

Examples would be useful

--~--~-~--~~~---~--~~
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
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: Typo on Refs and Transactions page

2008-12-18 Thread Daniel Eklund


 Fixed - thanks for the report.


ahh since you're here and responding, there is a reference to
'boot.clj'  at http://clojure.org/getting_started  which is no longer
valid.. this page also points to sourceforge ...

any plans for a bug/typo tracking system so we don't fill up the group
with too much noise?

daniel
--~--~-~--~~~---~--~~
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
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: 'require' doc string out of date?

2008-12-16 Thread Daniel Eklund

 In general, clojure-contrib is a good place to look to find examples
 of properly laid-out libs, as well as generally idiomatic Clojure
 code.

 --Chouser

Yeah, just recently I've taken to scanning the code in 'webjure' and
'swank' to see how things are done, rather than relying on the APIs.

I never got to downloading 'clojure-contrib' but the more I read the
group, the more it seems like this is where the magic is happening.
Thanks for the recommendation.
--~--~-~--~~~---~--~~
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
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: Is clojure.core/require documentation out of date ?

2008-12-16 Thread Daniel Eklund

 If I'm wrong, could you please help me understand, maybe by giving me
 a URL I may have missed ?

 Regards,

 --
 Laurent PETIT

yes it is out of date... check the post 5 posts down:

http://groups.google.com/group/clojure/browse_frm/thread/4a4c2e3e7aab5325#

--~--~-~--~~~---~--~~
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
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: Is clojure.core/require documentation out of date ?

2008-12-16 Thread Daniel Eklund


 I know don't feel comfortable with the notion of lib. I currently
 assume that it is more or less similar to a namespace : it looks like
 a namespace, it tastes like a namespace, but still does seem to be not
 considered a namespace.


I understand your pain.  I am right now going through the same thought
process, and do not have a satisfactory understanding myself.  The
myriad connections between namespaces and libraries as manifest
through 'load-file', 'require', 'use', 'refer', 'load', have left me
scratching my head.  In the end, someone like you or I might need to
publish our discoveries here (with the understanding that we are
looking for feedback).

I am currently going through the core.clj to understand the
dependencies.  I think you will find the API will stay out of date for
the short term as things are fleshed out here and on the IRC channel.

I thought that clojure was further along when I started a few weeks
ago.

Please don't mistake this last statement for a criticism.  In fact,
now that I see that I am in the middle of the birth of something
extremely impressive, I am rather excited.  The primitives and major
design decisions of this language seem to be solid.  It seems to be
these higher level notions that are being refined as we speak.  I've
dug up month-old to half-year old posts on this group where people
propose and implement breaking changes.  The AOT compilation change
came only a short time ago and seems to be the source of this
particular API staleness.  I've seen posts where the binding forms to
most of the sequencing funcitons are fleshed out on the group and then
committed.  There seems to be a great willingness to allow these
'API's to gestate in contrib libraries before they are promoted to
core -- after all, they're all just macros and functions in the end.

I am guessing this trend will continue for the foreseeable future, and
some examples, APIs and code libraries will be out of synch.  Heck, a
lot of the information I gleaned came from watching the movies, and
even those are out of date (there is no longer a boot.clj for
instance).

I think the best course of action, for now, is to just read the code.
Make core.clj your friend.  It has deepened my understanding of the
language decisions.  (Still trying to grok 'libraries' though :)

--~--~-~--~~~---~--~~
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
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: understanding quoting

2008-12-15 Thread Daniel Eklund

 Looks like an if then else version of the map lookup??
 ie: (if (%1 %2) (%1 %2) %3)
 Is this a special feature of maps in general, such that you can look
 up a key but return something else if it doesn't exist?
 I hadn't come across it yet, but it sounds useful :)

This is exactly right (I just confirmed it for myself).  I looked up
the java code for Keyword.java and Symbol.java both of which implement
IFn  (those things that can be put in the function position).  The
single and double arity invoke() merely delegate to 'get'.  And voila:

user (doc get)
-
clojure.core/get
([map key] [map key not-found])
  Returns the value mapped to key, not-found or nil if key not
present.

The last parameter is definitely for those situations where 'if not
found, use this'

I think I _finally_ understand the statement, keywords and symbols
are functions of maps.

So, the original poster's observation about ('+ '1 '2) returning '2
makes more sense when you consider that it turns into this:

(get '1 '+ '2)

or get from the hashmap ( '1 ) the value stored at key ( '+ ) and if
nil is returned, return ( '2 ) instead

(get '1 '+) returns nil as '1 is not even a map.


--~--~-~--~~~---~--~~
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
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: understanding quoting

2008-12-15 Thread Daniel Eklund

 How did you know that it delegates to 'get'?


sorry, I rushed that part.

the keyword and symbol are instances of clojure.lang.Keyword and
clojure.lang.Symbol
which are _java_ classes found in Keyword.java and Symbol.java (I
found these in the src/jvm directory)


These are what the invoke( ) methods looks like for the single and
double arity of both these classes (this is _java_ code):

/**
 * Indexer implements IFn for attr access
 *
 * @param obj - must be IPersistentMap
 * @return the value at the key or nil if not found
 * @throws Exception
 */
public Object invoke(Object obj) throws Exception{
return RT.get(obj, this);
}

public Object invoke(Object obj, Object notFound) throws Exception{
return RT.get(obj, this, notFound);
}


-
which in turn goes to RT.java

static public Object get(Object coll, Object key){
if(coll == null)
return null;
else if(coll instanceof Associative)
return ((Associative) coll).valAt(key);
else if(coll instanceof Map)
{
Map m = (Map) coll;
return m.get(key);
}
else if(coll instanceof IPersistentSet)
{
IPersistentSet set = (IPersistentSet) coll;
return set.get(key);
}
else if(key instanceof Number  (coll instanceof String ||
coll.getClass().isArray()))
{
int n = ((Number) key).intValue();
if(n = 0  n  count(coll))
return nth(coll, n);
return null;
}

return null;
}
static public Object get(Object coll, Object key, Object notFound){
if(coll == null)
return notFound;
else if(coll instanceof Associative)
return ((Associative) coll).valAt(key, notFound);
else if(coll instanceof Map)
{
Map m = (Map) coll;
if(m.containsKey(key))
return m.get(key);
return notFound;
}
else if(coll instanceof IPersistentSet)
{
IPersistentSet set = (IPersistentSet) coll;
if(set.contains(key))
return set.get(key);
return notFound;
}
else if(key instanceof Number  (coll instanceof String ||
coll.getClass().isArray()))
{
int n = ((Number) key).intValue();
return n = 0  n  count(coll) ? nth(coll, n) : notFound;
}
return notFound;

}


-

all really cool


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



My quest to modify a leaf node in an arbitrarily deep map (question posed)

2008-12-10 Thread Daniel Eklund

Hi all,

I am relatively new to clojure. I am trying to port some toy code I
wrote for common lisp a few years ago (a boggle-like game which needs
a dictionary prefix trie to trim possible word matches).

My old code was fairly imperative in nature when creating the
dictionary trie, and so now I am having fun exercising my brain trying
to do the right thing with functional programming.

One thing I immediately ran up against were certain situations where I
have a map and want to modify a value several levels deep into the
hierarchy.  Imagine the following structure:

(def nested-structure { :level 0,
 :nested1 { :level 1,
   :nested2 { :level 2,
 :final-data initial data}}})

If I need to change the value for :final-data,  the chain of nested
assoc, and  get becomes unwieldy (IMO).  So I spent several hours
scanning through the API to see what might help me out in this.  I
thought that the (-) macro was where it was at, but spun my wheels.
I thought potentially, that the destructuring capabilities of let
would help me out, but again I could not get anything to work the way
I wanted...  I played around with various reduce concoctions
(accumulating closures) and even toyed with generating a macro, before
I realized how easy it was:

;; keys is a vector of steps in a path, navigating down a map
hierarchy
(defn path-rebind [map keys val]
  (let [ [first  rest] keys
 nested-val (get map first) ]
(if rest
  (assoc map first (path-rebind nested-val rest val))
  (assoc map first val

user (path-rebind nested-structure [:nested1 :nested2 :final-data]
new data)
{:nested1 {:nested2 {:final-data new data, :level 2}, :level
1}, :level 0}

So, I have two questions:

1) Am I missing something from the API that could have done what my
function path-rebind? (I would have assumed that this would be a
common need and that programmers would not need to roll their own each
time)
2) Am I missing out on a clever reduce usage that could have made
this more in-line?  i.e. how's my code?

It was after I made wrote this function and contemplated how I could
make it abstract (i.e. with vectors, lists, etc) that I noticed the
existence of the zip library...  Maybe question 1) above is answered
by the zip library.  Is/Will the zip library be the recommended
means by which to navigate/modify data structures of arbitrary depth,
branching, and concrete 'type' ?


daniel



--~--~-~--~~~---~--~~
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
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: My quest to modify a leaf node in an arbitrarily deep map (question posed)

2008-12-10 Thread Daniel Eklund

  One thing I immediately ran up against were certain situations where
  I have a map and want to modify a value several levels deep into
  the hierarchy.  Imagine the following structure:

  (def nested-structure { :level 0,
                          :nested1 { :level 1,
                                    :nested2 { :level 2,
                                              :final-data initial data}}})

 Look into clojure.zip (.../src/clj/clojure/zip.clj in the Clojure
 source).


Excellent... thanks for the pointer.  I will take a stab at using this
for maps (I see stuff for vector-zip, but not yet maps).

As an off-hand comment made without careful reading, I can imagine
there being great utility in a special reader-syntax for paths.  XSLT
embeds xpath, and groovy embeds gpath.  I am unsure at this point the
exact capabilities of the zipper, so I don't know whether it's meant
to go to a single location in a tree (it seems this way) or whether it
refers to a sequence of all tree nodes that satisfy the predicates of
the path (as xpath and gpath do).  For the latter scenario, though, a
reader syntax for a path could be very useful.

thanks again !

daniel
--~--~-~--~~~---~--~~
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
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: My quest to modify a leaf node in an arbitrarily deep map (question posed)

2008-12-10 Thread Daniel Eklund

  user (path-rebind nested-structure [:nested1 :nested2 :final-data]
  new data)
  {:nested1 {:nested2 {:final-data new data, :level 2}, :level
  1}, :level 0}

 Congratulations, you've implemented 'assoc-in'  :-)

 user= (assoc-in nested-structure [:nested1 :nested2 :final-data] new data)
 {:nested1 {:nested2 {:level 2, :final-data new data}, :level 1}, :level 0}

 There are also 'get-in' and 'update-in'.

 Your code looks fine -- nearly identical to 'assoc-in' in fact.  It
 does the destructuring right in the function arguments, but everything
 else is merely stylistic differences.

 --Chouser

ahh even better...   I knew someone must have done this before and
it kills me now to look at the API and see it right underneath the
(assoc) description.   I have no idea how I missed it.

thanks,
daniel
--~--~-~--~~~---~--~~
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
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: Elegant but very slow

2008-12-04 Thread Daniel Eklund

I

On Dec 4, 2:55 pm, PeterB [EMAIL PROTECTED] wrote:
 Hi,

 I downloaded clojure_20080916.zip and had a go with a simple tree
 benchmark (cut-down version of the one in the computer language
 shootout  http://shootout.alioth.debian.org/).

 The Java version is pretty simple and runs in about 2s on my laptop:

 public class Main
 {
     public static void main(String[] args)
     {
         System.out.println(result:  + sumTrees(1, 10));
     }

     public static int sumTrees(int iterations, int depth)
     {
         int i;
         int sum = 0;

         for (i = 1; i = iterations; i++)
             sum += TreeNode.bottomUpTree(i, depth).itemCheck() +
                         TreeNode.bottomUpTree(-i, depth).itemCheck();
         return sum;
     }

     public static class TreeNode
     {
         private TreeNode left, right;
         private int           item;

         TreeNode(int item)
         {
             this.item = item;
         }

         TreeNode(int item, TreeNode left, TreeNode right)
         {
             this.left = left;
             this.right = right;
             this.item = item;
         }

         private static TreeNode bottomUpTree(int item, int depth)
         {
             if (depth  0)
                 return new TreeNode(item,
                                                bottomUpTree(2*item-1,
 depth-1),
                                                bottomUpTree(2*item,
 depth-1));
             else
                 return new TreeNode(item);
         }

         int itemCheck()
         {
             if (left == null)
                 return item;
             else
                 return item + left.itemCheck() - right.itemCheck();
         }
     }

 }

 The Clojure version is considerably more compact and elegant:

 (defn make-tree [item depth]
   (if (zero? depth)
     (list item nil nil)
     (let [item2 (* 2 item)  depth-1 (dec depth)]
       (list item (make-tree (dec item2) depth-1) (make-tree item2
 depth-1)

 (defn check-tree [tree]
   (if (nil? tree)
     0
     (let [[i l r] tree] (- (+ i (check-tree l)) (check-tree r)

 (defn sum-trees [iterations depth]
   (let [sum #(+ (check-tree (make-tree % depth))
                       (check-tree (make-tree (- %) depth)))]
     (reduce #(+ %1 %2) 0 (map sum (range 1 (inc iterations))

  (time (println result: (sum-trees 1 10)))

 However, there is a heavy price to be paid for this elegance:
 'Elapsed time: 100730.161515 msecs'

 Ouch! That's rather disappointing :-(
 Any suggestions for improving the performance?
--~--~-~--~~~---~--~~
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
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: Elegant but very slow

2008-12-04 Thread Daniel Eklund

  ahhh... to answer my own question (and if I had looked at the code
and the API a bit closer),
it turns out that recur can only be used in tail-position... and
your code (as a tree-recursor) would
not benefit from this.

On Dec 4, 5:39 pm, Daniel Eklund [EMAIL PROTECTED] wrote:
 oops...

 I am just learning the language right now and just quickly looked
 at what you did...
 Would the use of recur instead of self-calls potentially help
 consuming stack space?

 http://clojure.org/special_forms#toc10

 On Dec 4, 5:37 pm, Daniel Eklund [EMAIL PROTECTED] wrote:

  I

  On Dec 4, 2:55 pm, PeterB [EMAIL PROTECTED] wrote:

   Hi,

   I downloaded clojure_20080916.zip and had a go with a simple tree
   benchmark (cut-down version of the one in the computer language
   shootout  http://shootout.alioth.debian.org/).

   The Java version is pretty simple and runs in about 2s on my laptop:

   public class Main
   {
       public static void main(String[] args)
       {
           System.out.println(result:  + sumTrees(1, 10));
       }

       public static int sumTrees(int iterations, int depth)
       {
           int i;
           int sum = 0;

           for (i = 1; i = iterations; i++)
               sum += TreeNode.bottomUpTree(i, depth).itemCheck() +
                           TreeNode.bottomUpTree(-i, depth).itemCheck();
           return sum;
       }

       public static class TreeNode
       {
           private TreeNode left, right;
           private int           item;

           TreeNode(int item)
           {
               this.item = item;
           }

           TreeNode(int item, TreeNode left, TreeNode right)
           {
               this.left = left;
               this.right = right;
               this.item = item;
           }

           private static TreeNode bottomUpTree(int item, int depth)
           {
               if (depth  0)
                   return new TreeNode(item,
                                                  bottomUpTree(2*item-1,
   depth-1),
                                                  bottomUpTree(2*item,
   depth-1));
               else
                   return new TreeNode(item);
           }

           int itemCheck()
           {
               if (left == null)
                   return item;
               else
                   return item + left.itemCheck() - right.itemCheck();
           }
       }

   }

   The Clojure version is considerably more compact and elegant:

   (defn make-tree [item depth]
     (if (zero? depth)
       (list item nil nil)
       (let [item2 (* 2 item)  depth-1 (dec depth)]
         (list item (make-tree (dec item2) depth-1) (make-tree item2
   depth-1)

   (defn check-tree [tree]
     (if (nil? tree)
       0
       (let [[i l r] tree] (- (+ i (check-tree l)) (check-tree r)

   (defn sum-trees [iterations depth]
     (let [sum #(+ (check-tree (make-tree % depth))
                         (check-tree (make-tree (- %) depth)))]
       (reduce #(+ %1 %2) 0 (map sum (range 1 (inc iterations))

    (time (println result: (sum-trees 1 10)))

   However, there is a heavy price to be paid for this elegance:
   'Elapsed time: 100730.161515 msecs'

   Ouch! That's rather disappointing :-(
   Any suggestions for improving the performance?
--~--~-~--~~~---~--~~
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
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---



Re: Clojure HTML Documentation

2008-11-21 Thread Daniel Eklund

beautiful !

thanks... i was just looking for something like this

On Nov 21, 3:17 am, Mark McGranaghan [EMAIL PROTECTED] wrote:
 I've created some experimental HTML docs for Clojure. You can see them
 on S3:http://clj-doc.s3.amazonaws.com/tmp/doc-1116/index.html

 Or, just for kicks, on Amazon's new Cloud Front 
 CDN:http://d2nbqsesuabw8o.cloudfront.net/tmp/doc-1116/index.html

 You can see the code I used to generate them on 
 GitHub:http://github.com/mmcgrana/clj-doc

 The generation code is open for public perusal but will require some
 tweaking for public use (e.g. I still have paths hard coded). Any help
 along these lines would be greatly appreciated.

 Most methods in the clj-doc source have docstrings and in total its
 only a couple hundred lines of code: you should be able to find your
 way around if you're interested. The best entry point is bin/gen.clj.
 Again, any comments or suggests would be appreciated.

 I hope that some of you find this interesting/useful/helpful in your
 Clojure endeavors,
 - Mark

--~--~-~--~~~---~--~~
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
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~--~~~~--~~--~--~---