Re: Why don't extends? and satisfies? require implementation of all protocol methods?

2012-03-09 Thread Armando Blancas
I just want to point out that I incorrectly stated that Clojure generates 
abstract stubs for unimplemented protocol methods (or types, for that 
matter). In fact, Clojure does nothing about them. For classes to fully 
implement interfaces is enforced by the Java compiler, not the JVM.

On Thursday, March 8, 2012 11:40:20 PM UTC-8, Garth Sheldon-Coulson wrote:

 I think Tassilo's ideas about extenders deserve more discussion. But let 
 me continue the discussion with Armando for now.

 Thank you for offering the Eclipse API example, which is very helpful. I 
 agree that Java's OO paradigm creates the need for abstract classes. 
 However, I would like to look further at what is going on in the Eclipse 
 example and consider if protocols in Clojure are the same or different.

 To clarify the example: Eclipse allows the user to add the user's own 
 methods for certain kinds of event-handling. Because the language is Java, 
 these methods must be attached to a class. In order for Eclipse to specify 
 which methods it expects, Eclipse provides an interface that the user's 
 class must implement. For convenience, Eclipse also provides default 
 implementations of the required methods; these are provided in an abstract 
 class. When the user extends this abstract class, the user can elect to 
 override none, some, or all of the default methods.

 I have a few observations.

 1) In the example, it is certainly true that the user may implement none 
 or just some of the methods of the interface. However, when the user 
 finally passes an object instance to Eclipse, *all* of the methods of the 
 interface are in fact implemented by that instance. This is because the 
 default implementations in the abstract class will fill any holes the user 
 leaves. Therefore, I respectfully disagree that this is case of partial 
 implementation. It may appear so to the user, but not to the language.

 2) It is true that a Java abstract class can partially implement an 
 interface. However, an abstract class cannot be instantiated. It must be 
 extended first. When extending an abstract class, the user must implement 
 any methods that the abstract class has not implemented. No concrete class 
 partially implements an interface.

 To me, the analogy to Java therefore supports the idea that the extends? 
 relationship ought to require a datatype/record to implement all of its 
 protocols' methods. A datatype/record is a piece of data, not a collection 
 of default methods; it is therefore like an object instance, not an 
 abstract class. Object instances must implement all of their interfaces' 
 methods.

 As I said in my last post, it would seem strange for a language to provide 
 protocols (rather than just fast, un-grouped multimethods) if a piece of 
 data that satisfies a protocol does not necessarily implement even one of 
 the protocol's methods.

 3) Armando's worry is valid that requiring implementation of protocol 
 methods would result in proliferation of interfaces and protocols that 
 would prevent reuse; something like 
 ListWithoutModificationOrBulkOperations. 

 However, to me the beauty of protocols is that they can be highly 
 granular. They are not tied to a rigid inheritance paradigm. They support 
 direct implementation composition. If, per Armando's example, a protocol 
 designer felt the need to have a BasicList protocol, a ModifiableList 
 protocol, and a BulkOperations protocol, to be combined as necessary, that 
 would be just fine. 

 4) In /The Joy of Clojure/, a few of the examples involve extending a type 
 to implement just one of a protocol's multiple methods (pp. 193-195). The 
 authors consider this a valid use case. To leave the /JoC/ examples roughly 
 intact while giving protocols a bit more bite, let me throw out two ideas 
 for discussion.

 Idea 1
 ==

 Types may be extended to a strict subset of a protocol's methods, but 
 satisfies? and extends? will return FALSE, not true, in this case. That is:

 = (defprotocol Fixo
  (fixo-push [fixo value])
  (fixo-pop [fixo]))
 Fixo
   
 = (extend-type clojure.lang.IPersistentVector
  Fixo
  (fixo-push [vector value]
(conj vector value)))
 [succeeds]

 = (extends? Fixo clojure.lang.IPersistentVector)
 FALSE, not true


 Idea 2
 ==

 Types may be extended to new protocols only if *all* of the protocol's 
 methods are implemented. However, types may be always extended tonew, 
 ungrouped *methods*. That is:

 = (defprotocol Fixo
  (fixo-push [fixo value])
  (fixo-pop [fixo]))
 Fixo
   
 = (extend-type clojure.lang.IPersistentVector
  Fixo
  (fixo-push [vector value]
(conj vector value)))
 [should FAIL - protocol name not allowed here unless all methods are 
 implemented]  

 = (extend-type clojure.lang.IPersistentVector
  nil
  (fixo-push [vector value]
(conj vector value)))
 [should SUCCEED - fixo-push is like a fast multimethod, without a named 
 protocol]

 = (extends? Fixo 

Re: Why don't extends? and satisfies? require implementation of all protocol methods?

2012-03-08 Thread Armando Blancas
(Don't know why I can only respond to the first message.)

I come across partial implementation all the time, and with proxy, too. In 
Eclipse this is so common that this is typical:

This adapter class provides default implementations for the methods 
described by the SelectionListener interface.
Classes that wish to deal with SelectionEvents can extend this class and 
override only the methods which they are interested in.

You may have seen the idea of optional operation in java.util.List and how 
it's handled in places like AbstractList with default implementations. 
Clojure itself has partial implementations of List in PersistentList and 
Collection in PersistentQueue. I suppose the alternative would be a 
proliferation of interfaces and protocols that would prevent reuse; 
something like ListWithoutModificationOrBulkOperations could have a full 
implementation but little use.

I can see the value of your view of protocol as spec, but maybe for 
domain-realted concepts and less for plumbing. 

-- 
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: Why don't extends? and satisfies? require implementation of all protocol methods?

2012-03-08 Thread Garth Sheldon-Coulson
I think Tassilo's ideas about extenders deserve more discussion. But let me 
continue the discussion with Armando for now.

Thank you for offering the Eclipse API example, which is very helpful. I 
agree that Java's OO paradigm creates the need for abstract classes. 
However, I would like to look further at what is going on in the Eclipse 
example and consider if protocols in Clojure are the same or different.

To clarify the example: Eclipse allows the user to add the user's own 
methods for certain kinds of event-handling. Because the language is Java, 
these methods must be attached to a class. In order for Eclipse to specify 
which methods it expects, Eclipse provides an interface that the user's 
class must implement. For convenience, Eclipse also provides default 
implementations of the required methods; these are provided in an abstract 
class. When the user extends this abstract class, the user can elect to 
override none, some, or all of the default methods.

I have a few observations.

1) In the example, it is certainly true that the user may implement none or 
just some of the methods of the interface. However, when the user finally 
passes an object instance to Eclipse, *all* of the methods of the interface 
are in fact implemented by that instance. This is because the default 
implementations in the abstract class will fill any holes the user leaves. 
Therefore, I respectfully disagree that this is case of partial 
implementation. It may appear so to the user, but not to the language.

2) It is true that a Java abstract class can partially implement an 
interface. However, an abstract class cannot be instantiated. It must be 
extended first. When extending an abstract class, the user must implement 
any methods that the abstract class has not implemented. No concrete class 
partially implements an interface.

To me, the analogy to Java therefore supports the idea that the extends? 
relationship ought to require a datatype/record to implement all of its 
protocols' methods. A datatype/record is a piece of data, not a collection 
of default methods; it is therefore like an object instance, not an 
abstract class. Object instances must implement all of their interfaces' 
methods.

As I said in my last post, it would seem strange for a language to provide 
protocols (rather than just fast, un-grouped multimethods) if a piece of 
data that satisfies a protocol does not necessarily implement even one of 
the protocol's methods.

3) Armando's worry is valid that requiring implementation of protocol 
methods would result in proliferation of interfaces and protocols that 
would prevent reuse; something like 
ListWithoutModificationOrBulkOperations. 

However, to me the beauty of protocols is that they can be highly granular. 
They are not tied to a rigid inheritance paradigm. They support direct 
implementation composition. If, per Armando's example, a protocol designer 
felt the need to have a BasicList protocol, a ModifiableList protocol, and 
a BulkOperations protocol, to be combined as necessary, that would be just 
fine. 

4) In /The Joy of Clojure/, a few of the examples involve extending a type 
to implement just one of a protocol's multiple methods (pp. 193-195). The 
authors consider this a valid use case. To leave the /JoC/ examples roughly 
intact while giving protocols a bit more bite, let me throw out two ideas 
for discussion.

Idea 1
==

Types may be extended to a strict subset of a protocol's methods, but 
satisfies? and extends? will return FALSE, not true, in this case. That is:

= (defprotocol Fixo
 (fixo-push [fixo value])
 (fixo-pop [fixo]))
Fixo
  
= (extend-type clojure.lang.IPersistentVector
 Fixo
 (fixo-push [vector value]
   (conj vector value)))
[succeeds]

= (extends? Fixo clojure.lang.IPersistentVector)
FALSE, not true


Idea 2
==

Types may be extended to new protocols only if *all* of the protocol's 
methods are implemented. However, types may be always extended tonew, 
ungrouped *methods*. That is:

= (defprotocol Fixo
 (fixo-push [fixo value])
 (fixo-pop [fixo]))
Fixo
  
= (extend-type clojure.lang.IPersistentVector
 Fixo
 (fixo-push [vector value]
   (conj vector value)))
[should FAIL - protocol name not allowed here unless all methods are 
implemented]  

= (extend-type clojure.lang.IPersistentVector
 nil
 (fixo-push [vector value]
   (conj vector value)))
[should SUCCEED - fixo-push is like a fast multimethod, without a named 
protocol]

= (extends? Fixo clojure.lang.IPersistentVector)
FALSE, not true


I invite discussion and criticism.

All the best, Garth


On Thursday, March 8, 2012 11:24:42 AM UTC-5, Armando Blancas wrote:

 (Don't know why I can only respond to the first message.)

 I come across partial implementation all the time, and with proxy, too. In 
 Eclipse this is so common that this is typical:

 This adapter class provides default implementations for the methods 
 described by the 

Re: Why don't extends? and satisfies? require implementation of all protocol methods?

2012-03-07 Thread Tassilo Horn
Garth Sheldon-Coulson garth.sheldoncoul...@gmail.com writes:

Hi Garth,

 I'm returning to Clojure in earnest for the first time since 1.1 (and
 very happy to be back!). Apologies if this question revisits old
 issues.

I've revisited mostly the same 2 days ago: 87399ocg9a@thinkpad.tsdh.de

 I'm trying to understand why the semantics of protocols are such that
 the third statement here returns true:

 user= (defprotocol Bashable (bash [this]) (boom [this]))
 Bashable

 user= (defrecord Record [] Bashable (bash [this] bash!))
 user.Record

 user= (and (satisfies? Bashable (Record.)) (extends? Bashable
 Record))
 true

 This returns true even though boom is not implemented for Record:

 user= (boom (Record.))
 AbstractMethodError user.Record.boom()Ljava/lang/Object;  user/eval55
 (NO_SOURCE_FILE:3)

 Apparently, types/records can implement a protocol in name only.

What do you mean with in name only?

 What is behind this choice? Intuitively, I would have conceived of a
 protocol as a collection of methods all of which must be implemented
 in order for a type/record to extend the protocol.

I think it would be nice if extends?/satisfies? would return the set of
implemented methods, say, as keywords.  Then you could check if an
object implements exactly the methods that your function wants to call.

 A second question. How does one explicitly extend a protocol per the
 documentation of the extenders function? Intuitively, I would have
 thought that the code above explicitly extends Bashable if it
 extends Bashable at all. Yet:

 user= (extenders Bashable)
 nil

That was my initial question in my posting two days ago.  extenders
returns only types that extend a protocol using the `extend' function
(or `extend-type', `extend-protocol' macros).  So this works:

  user (defprotocol Bashable (bash [this]) (boom [this]))
  Bashable
  user (defrecord Record [])
  user.Record
  user (extend-protocol Bashable
   Record (bash [_] Bash!))
  nil
  user (extenders Bashable)
  (user.Record)

IMO, that behavior is not very obvious.

OTOH, Stu said that extenders is specific to the extend form (as
suggested by its name), and in fact, neither defrecord's nor deftype's
documentation speak of extending a protocol, but their terminology is to
supply method implementations for protocol methods.

But then, what's the use case of `extenders' anyway?  I mean, I want to
know what types participate in a protocol.  I don't care if they do
because they were explicitly extended to the protocol or because the
method implementations were provided directly in their definition form.
That's an implementation detail I shouldn't have to bother with...

Bye,
Tassilo

-- 
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: Why don't extends? and satisfies? require implementation of all protocol methods?

2012-03-07 Thread David Powell
When you create a protocol, as an implementation detail, it also creates a
Java interface.

When you list protocols in a deftype or defrecord form, the generated class
actually implements that Java interface.  And protocol calls to that type
call through the interface. This gives the best performance.

If you add protocols to an existing class, record or type; this dispatch is
done dynamically and interfaces aren't involved.

-- 
Dave
On Mar 7, 2012 8:09 AM, Tassilo Horn tass...@member.fsf.org wrote:

 Garth Sheldon-Coulson garth.sheldoncoul...@gmail.com writes:

 Hi Garth,

  I'm returning to Clojure in earnest for the first time since 1.1 (and
  very happy to be back!). Apologies if this question revisits old
  issues.

 I've revisited mostly the same 2 days ago: 
 87399ocg9a@thinkpad.tsdh.de

  I'm trying to understand why the semantics of protocols are such that
  the third statement here returns true:
 
  user= (defprotocol Bashable (bash [this]) (boom [this]))
  Bashable
 
  user= (defrecord Record [] Bashable (bash [this] bash!))
  user.Record
 
  user= (and (satisfies? Bashable (Record.)) (extends? Bashable
  Record))
  true
 
  This returns true even though boom is not implemented for Record:
 
  user= (boom (Record.))
  AbstractMethodError user.Record.boom()Ljava/lang/Object;  user/eval55
  (NO_SOURCE_FILE:3)
 
  Apparently, types/records can implement a protocol in name only.

 What do you mean with in name only?

  What is behind this choice? Intuitively, I would have conceived of a
  protocol as a collection of methods all of which must be implemented
  in order for a type/record to extend the protocol.

 I think it would be nice if extends?/satisfies? would return the set of
 implemented methods, say, as keywords.  Then you could check if an
 object implements exactly the methods that your function wants to call.

  A second question. How does one explicitly extend a protocol per the
  documentation of the extenders function? Intuitively, I would have
  thought that the code above explicitly extends Bashable if it
  extends Bashable at all. Yet:
 
  user= (extenders Bashable)
  nil

 That was my initial question in my posting two days ago.  extenders
 returns only types that extend a protocol using the `extend' function
 (or `extend-type', `extend-protocol' macros).  So this works:

  user (defprotocol Bashable (bash [this]) (boom [this]))
  Bashable
  user (defrecord Record [])
  user.Record
  user (extend-protocol Bashable
   Record (bash [_] Bash!))
  nil
  user (extenders Bashable)
  (user.Record)

 IMO, that behavior is not very obvious.

 OTOH, Stu said that extenders is specific to the extend form (as
 suggested by its name), and in fact, neither defrecord's nor deftype's
 documentation speak of extending a protocol, but their terminology is to
 supply method implementations for protocol methods.

 But then, what's the use case of `extenders' anyway?  I mean, I want to
 know what types participate in a protocol.  I don't care if they do
 because they were explicitly extended to the protocol or because the
 method implementations were provided directly in their definition form.
 That's an implementation detail I shouldn't have to bother with...

 Bye,
 Tassilo

 --
 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: Why don't extends? and satisfies? require implementation of all protocol methods?

2012-03-07 Thread Tassilo Horn
David Powell d...@djpowell.net writes:

Hi David,

 When you create a protocol, as an implementation detail, it also
 creates a Java interface.

Is a protocal neccessarily an implementation detail?  I mean, it might
be, but it can also be a public specification of the requirements types
have to satisfy in order to integrate with my lib.

 When you list protocols in a deftype or defrecord form, the generated
 class actually implements that Java interface.  And protocol calls to
 that type call through the interface. This gives the best performance.

 If you add protocols to an existing class, record or type; this
 dispatch is done dynamically and interfaces aren't involved.

That suggests that `extenders' is actually a private function for doing
the dynamic dispatch.  But it's not used at all in clojure.core.  And
it's inconsistent with extends?.

user (defrecord R2 [] Bashable (boom [this] :boom))
user.R2
user (extenders Bashable);; just returns the dynamic extenders
(user.Record)
user (extends? Bashable R2)  ;; does an implements? check as well
true

IMHO, `extenders' should return also types implementing the protocol
interface directly, so that

  (extends? P T) = (some #(= % T) (extenders P))

holds.

Bye,
Tassilo

-- 
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: Why don't extends? and satisfies? require implementation of all protocol methods?

2012-03-07 Thread Alan Malloy
On Mar 7, 1:09 am, Tassilo Horn tass...@member.fsf.org wrote:
 David Powell d...@djpowell.net writes:

 Hi David,

  When you create a protocol, as an implementation detail, it also
  creates a Java interface.

 Is a protocal neccessarily an implementation detail?  I mean, it might
 be, but it can also be a public specification of the requirements types
 have to satisfy in order to integrate with my lib.

You misread his assertion. The implementation detail is that an
interface is defined along with each protocol.

  When you list protocols in a deftype or defrecord form, the generated
  class actually implements that Java interface.  And protocol calls to
  that type call through the interface. This gives the best performance.

  If you add protocols to an existing class, record or type; this
  dispatch is done dynamically and interfaces aren't involved.

 That suggests that `extenders' is actually a private function for doing
 the dynamic dispatch.  But it's not used at all in clojure.core.  And
 it's inconsistent with extends?.

I don't really see how it suggests that, but okay. It does appear that
you're right that extenders and extends? are not consistent between
each other.

 user (defrecord R2 [] Bashable (boom [this] :boom))
 user.R2
 user (extenders Bashable)    ;; just returns the dynamic extenders
 (user.Record)
 user (extends? Bashable R2)  ;; does an implements? check as well
 true

 IMHO, `extenders' should return also types implementing the protocol
 interface directly, so that

   (extends? P T) = (some #(= % T) (extenders P))

 holds.

You're entitled to that humble opinion, but it's not really possible
with any kind of reasonable performance. When you implement the
protocol interface directly, no machinery in clojure.core gets
involved at all - you just define a class that implements an
interface. For `extenders` to be able to list Java classes that
implement the interface directly, it would have to walk through every
class loaded in the JVM and check its implemented-interfaces.

Of course, you could make it almost-work, by having deftype/defrecord
emit some special code for hooking into extenders whenever you define
a class in Clojure, but then it would only work for classes defined
within Clojure, and not for Java classes that implement Clojure's
interfaces/protocols. Frankly I think that's worse than just limiting
it to dynamic extenders.

-- 
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: Why don't extends? and satisfies? require implementation of all protocol methods?

2012-03-07 Thread Tassilo Horn
Alan Malloy a...@malloys.org writes:

Hi Alan,

 IMHO, `extenders' should return also types implementing the protocol
 interface directly [i.e., deftypes and defrecords], so that

   (extends? P T) = (some #(= % T) (extenders P))

 holds.

 You're entitled to that humble opinion, but it's not really possible
 with any kind of reasonable performance. When you implement the
 protocol interface directly, no machinery in clojure.core gets
 involved at all - you just define a class that implements an
 interface. For `extenders` to be able to list Java classes that
 implement the interface directly, it would have to walk through every
 class loaded in the JVM and check its implemented-interfaces.

 Of course, you could make it almost-work, by having deftype/defrecord
 emit some special code for hooking into extenders whenever you define
 a class in Clojure,

That's what I had in mind.  deftype/defprotocol could just alter the
:impls of the protocol, just like `extend' does.

 but then it would only work for classes defined within Clojure, and
 not for Java classes that implement Clojure's interfaces/protocols.

Well, yes.

 Frankly I think that's worse than just limiting it to dynamic
 extenders.

I'd prefer if it was limited to extenders that extend within clojure,
because that seems to be the more common case.  My use case for
`extenders' was my API docs generator, where I'd like to add to every
protocol description the types that extend that protocol.

So basically, I see 3 options:

  1) rename `extenders' to `dynamic-extenders' (or something like that)
 to get rid of the extends?/extenders inconsistency

  2) remove `extenders' completely (can anyone think of any use case for
 it in its current incarnation that is important enough that it
 justifies a core function instead of using (keys (:impls protocol))
 directly?)

  3) make deftype/defrecord alter the :impls just like `extend' does and
 document the limitation concerning implementing protocol interfaces
 in java explicitly in the `extenders' docstring

I'm happy to provide a patch for either option.

Bye,
Tassilo

-- 
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: Why don't extends? and satisfies? require implementation of all protocol methods?

2012-03-07 Thread Armando Blancas


 user= (boom (Record.)) 
 AbstractMethodError user.Record.boom()Ljava/lang/Object;  user/eval55 
 (NO_SOURCE_FILE:3) 

 Apparently, types/records can implement a protocol in name only. 


That can't in name only since you obviously got an implementation, though 
abstract.
 

 What is behind this choice? 


That's convenient when an implementation only cares about a few methods in 
a big protocol.

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

Why don't extends? and satisfies? require implementation of all protocol methods?

2012-03-06 Thread Garth Sheldon-Coulson
I'm returning to Clojure in earnest for the first time since 1.1 (and
very happy to be back!). Apologies if this question revisits old
issues.

I'm trying to understand why the semantics of protocols are such that
the third statement here returns true:

user= (defprotocol Bashable (bash [this]) (boom [this]))
Bashable

user= (defrecord Record [] Bashable (bash [this] bash!))
user.Record

user= (and (satisfies? Bashable (Record.)) (extends? Bashable
Record))
true

This returns true even though boom is not implemented for Record:

user= (boom (Record.))
AbstractMethodError user.Record.boom()Ljava/lang/Object;  user/eval55
(NO_SOURCE_FILE:3)

Apparently, types/records can implement a protocol in name only.
What is behind this choice? Intuitively, I would have conceived of a
protocol as a collection of methods all of which must be implemented
in order for a type/record to extend the protocol.

A second question. How does one explicitly extend a protocol per the
documentation of  the extenders function? Intuitively, I would have
thought that the code above explicitly extends Bashable if it
extends Bashable at all. Yet:

user= (extenders Bashable)
nil

Thank you.

All the best, Garth Sheldon-Coulson

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