On the subject of per defmulti hierarchies:

The recent CLJOS thread got me thinking about this problem again.  
While allowing per-multimethod hierarchies solves a large number  
problems, I think it might be lacking for a class of needs. I think I  
have solution that can provide for multiple hierarchies and meet this  
larger class to which I allude. Allow me to provide an illustration.  
Say I have a step-wise mathematical function. From less than or equal  
to zero, return zero. From more than zero to less than equal to five,  
return the value. Above 5, square the value.

I could implement that as multimethod:

(defmulti stepwise (fn [n] (cond (>= 0 n) :zero (and (> n 0) (< n  
5)) :zero-five :else :above-five)))
(defmethod stepwise :zero [_] 0)
(defmethod stepwise :zero-five [x] x)
(defmethod stepwise :above-five [x] (* x x))

I've left an intentional programming error in to show how easy it is  
to make an error with such (cond ...) based dispatch. Yuck.

But there is a better way. What if I could supply my own function to  
decide which key matched the multimethod (not what the key is for the  
value, but how the key maps to a multimethod). Currently all we have  
is isa?, but if this were only the default? My example might look  
something like:

(defmulti stepwise identity <=)
(defmethod stepwise 0 [_] 0)
(defmethod stepwise 5 [n] n)
(defmethod stepwise :default [n] (* n n))
(prefer-method stepwise 0 5) ; since -1 < 0 and -1 < 5

I find this much cleaner, and the subtle error above was been  
eliminated. And if I want to add another case, its not too hard  
(though the number of prefer-methods might increase exponentially).  
This is a rather trivial case, but I think it makes the need clear:  
per-multi comparison functions.

For multiple hierarchies, this would be a common idiom:
(defmulti mymulti dispatch-function (fn [object-key method-key] (isa?  
*my-hiearchy* object-key method-key))

A user could use a ref or atom as needed, no special casing in the  
Clojure code.

What do people think?
-Mark


On Jan 7, 2009, at 10:44 AM, Meikel Brandmeyer wrote:

> Hi Rich,
>
> Am 07.01.2009 um 17:10 schrieb Rich Hickey:
>
>> Thanks Meikel. I have a couple of points:
>>
>> First, making derive and underive act on vars instead of the
>> hierarchies directly is not good - it reduces the generality
>> needlessly. Good practice is to make pure fns, then do the reference
>> part, not mix the two.
>>
>> Second, there's no reason to bind MultiFn to Var - any IRef will do.
>> Then people can put their hierarchies in Atoms/Refs or whatever.
>>
>> Third, I don't see the need for defhierarchy at this point.
>
> Ok. My problem is, that passing the hierarchy directly
> doesn't allow adding further derivations. The only idea
> I had, was to use Vars. I didn't like the idea, but I
> couldn't come up with another one. The solution is again
> an abstraction: IRef. Changing (un)derive and adding
> defhierarchy, was just some try to help the user with
> the limitations of this approach.
>
> But (dosync (alter ref-to-hierarchy derive ::Foo ::Bar))
> works perfectly. :) Much cleaner indeed. This shows
> again: ugly solutions and special cases are a sign,
> that one does it wrong...
>
> Please find attached another patch going for IRef instead
> of Var directly. And without the other cruft.
>
> Sincerely
> Meikel
>
> <issue-8b.diff>

- Mark Fredrickson
mark.m.fredrick...@gmail.com
http://www.markmfredrickson.com







--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To post to this group, send email to clojure@googlegroups.com
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
-~----------~----~----~----~------~----~------~--~---

Reply via email to