Design question: I made a new branch of the code where you extend the Is-A
protocol on the parent instead of the child. My reasoning is that when you
define multimethods, the dispatch value is the parent of the is-a
relation. Since you control these values, and have less control over the
child (~= the user's input to your multimethod), it makes more sense to
extend the protocol on the parent. Does that seem reasonable?
As a result, you can do some interesting things now. Here are some
examples from the test suite:
(is (true? (is-a? "" string?)))
(is (false? (is-a? [] seq))) ; nil -> false
(is (true? (is-a? [1] seq)))
(testing "even anonymous fns work."
(is (true? (is-a? [:kw "str" 1] ;; first number is a 1?
#(if-let [x (first (filter number? %))] (= x 1)))))
(is (false? (is-a? [:kw 2 "str" 1] ;; first number is a 1?
#(if-let [x (first (filter number? %))] (= x 1))))))))
(is (true? (is-a? {:a 1 :b "foo" :c Double :d "exact" :e :other}
{:a number? :b #"foo.*" :c Number :d "exact"})))
In case you weren't paying close attention, you can dispatch on any
predicate, on a regex matching an input string, on a map subsuming the
input map, any rule that core/isa? uses, and / or... lots of other things
you want to do, but I can't think of. It's starting to look like a pattern
matcher. Maybe it's starting to look like something else to you, too, but
let's keep it friendly :)
Downsides:
- You can extend a multimethod you don't control like this, but you'd
better pray you don't introduce ambiguities. By the way, with this much
flexibility, you *will* introduce ambiguities. core/isa?, derive, etc.
are designed to detect ambiguity and have you resolve it by hand.
Predicate dispatch will, among its other lovely qualities, detect (most?)
ambiguous, implied, or impossible dispatch predicates.
- Slow. If you're dispatching to a fn that runs for > 10ms, it's not a
huge problem. But, yeah, it's a lot slower than any other kind of
dispatch. But if you're doing dispatch this complicated, the speedy
alternative is giant nested cond and case statements.
As always comments, etc. welcome.
--Leif
On Wednesday, July 11, 2012 2:16:30 AM UTC-4, Leif wrote:
>
> Hi, everybody. I reimplemented the function isa? in terms of a protocol
> Is-A.
>
> The reason why you would want to do that is in the README at
> https://github.com/leifp/clj-isa-protocol
>
> tl;dr: One of the reasons why people are excited about predicate dispatch
> is the irritation caused by the dispatch function of a multimethod being
> closed. You have to decide up front what information the dispatch fn is
> going to pull out of your arguments. Changing it afterward is a pain.
>
> Since the dispatch uses 'isa?' internally, if that function is extensible,
> then multimethod dispatch becomes, to a certain extent, open. See the
> README.
>
> Comments, critique, code, and questions welcome.
>
> Cheers,
> Leif
>
> P.S. As an aside to people that like weird, obscure programming
> languages, the rough idea of how is-a? should work for maps was inspired by
> (but very much simpler than) the functional logic language LIFE [
> http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.90.3175 ]
>
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
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