David Nolen <[email protected]> writes:
Hi David,
>> In my patterns, I want to have a :+type key with a value that's
>> basically an interface name given as a symbol. The pattern should
>> match, if the class of the object implements that interface (or an
>> extended interface thereof) directly or indirectly. So that would be
>> my ideal user interface:
>>
>> --8<---------------cut here---------------start------------->8---
>> (match [obj]
>> [{:+type 'Cat :mice 4}] :1
>> [{:+type 'Dog :cats 3}] :2
>> [{:+type 'Mammal}] :3
>> :else :nope)
>> --8<---------------cut here---------------end--------------->8---
>
> This is a known missing feature and there's a couple of open questions
> as far as how to best implement this. It should probably support Java
> classes, Java interfaces, types, records, protocols and high
> performance hinted access to fields.
I'm not sure, if you've stopped reading there, so let me make my issue
clear. I'm *not* especially interested in some new feature for
efficiently matching on types, although that wouldn't be bad either.
What I'd like to have was a way to influence when a certain key with a
certain value matches for my IMatchLookup extending custom type. So if
IMatchLookup/val-at would be allowed to return a predicate that given
the value from the pattern tests if the match succeeds.
Here's a patch against the master version of core.match that makes my
Cat, Dog, Mamal example work, but it's only meant for illustration.
--8<---------------cut here---------------start------------->8---
--- a/src/main/clojure/clojure/core/match.clj
+++ b/src/main/clojure/clojure/core/match.clj
@@ -864,8 +864,12 @@
(to-source* [this ocr]
(cond
(= l ()) `(empty? ~ocr)
- (and (symbol? l) (not (-> l meta :local))) `(= ~ocr '~l)
- :else `(= ~ocr ~l)))
+ (and (symbol? l) (not (-> l meta :local))) `(if (fn? ~ocr)
+ (~ocr '~l)
+ (= ~ocr '~l))
+ :else `(if (fn? ~ocr)
+ (~ocr ~l)
+ (= ~ocr ~l))))
Object
(toString [_]
(if (nil? l)
--8<---------------cut here---------------end--------------->8---
I changed the LiteralPattern to-source* function to include a check if
ocr is a function. In that case, I apply it to the value l, else I
stick to the usulal (= ocr l) comparison. With that change, I can make
my val-at implementations return predicates like so:
--8<---------------cut here---------------start------------->8---
(extend-protocol IMatchLookup
;; ...
de.uni_koblenz.jgralab.Vertex
(val-at [this k not-found]
(case k
:+type (fn [x]
((core/type-matcher (graph this) x) this))
;; ...
(match-attribute this k not-found))))))
--8<---------------cut here---------------end--------------->8---
That makes my Cat, Dog, Mammal example work fine. But of course, it
works only for literal patterns, whereas my `type-matcher' function
above also accepts type specifications like [:and !Cat !Dog!] meaning
the object's type must be not a Cat and not exactly a Dog (but some Dog
subtype would be fine, and of course Birds, Fish, etc.).
So how would one tackle that issue in a general way? I guess, we'd need
some new pattern type, PredicatePattern, right? What might be a good
syntax for it? If you beat me to it, I'd give it a shot.
Bye,
Tassilo
--
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