On Aug 3, 5:54 pm, Brian Marick <[email protected]> wrote:
> In Midje, I have reason to create a type Metaconstant whose instances are
> "equal" to a symbol with the same name. Here's the relevant bits of the
> definition:
>
> (deftype Metaconstant [name storage]
> Object
> (equals [this that]
> (if (instance? (class this) that)
> (= (.name this) (.name that))
> (= (.name this) that)))
>
> clojure.lang.IPersistentCollection
> (equiv [this that]
> (println "equiv is called with" (type this) (type that))
> (.equals this that)))
>
> That's fine when a Metaconstant is compared to a symbol, but I thought I'd
> have to engage in hackery when a symbol is compared to a Metaconstant. That
> is:
>
> (println "= symbol metaconstant?")
> (println (= '...name... (Metaconstant. '...name... {}))) ; expect false
> (println "= metaconstant symbol?")
> (println (= (Metaconstant. '...name... {}) '...name... )) ; expect true
>
> Surprisingly, both directions produce true. That's because the order in which
> `.equiv` is called doesn't seem to depend on the order of arguments to `=`:
>
> = symbol metaconstant?
> equiv is called with midje.ideas.t-m.Metaconstant clojure.lang.Symbol
> true
> = metaconstant symbol?
> equiv is called with midje.ideas.t-m.Metaconstant clojure.lang.Symbol
> true
>
> Why is .equiv called with reordered arguments? And can I depend on that
> behavior going forward?
>
> I see this behavior with 1.2.0, 1.2.1, and 1.3.0-beta1.
clojure.lang.Util:
static public boolean equiv(Object k1, Object k2){
if(k1 == k2)
return true;
if(k1 != null)
{
if(k1 instanceof Number && k2 instanceof Number)
return Numbers.equal((Number)k1, (Number)k2);
else if(k1 instanceof IPersistentCollection || k2 instanceof
IPersistentCollection)
return pcequiv(k1,k2);
return k1.equals(k2);
}
return false;
}
static public boolean pcequiv(Object k1, Object k2){
if(k1 instanceof IPersistentCollection)
return ((IPersistentCollection)k1).equiv(k2);
return ((IPersistentCollection)k2).equiv(k1);
}
It strives to make sure that, if only one operand is a
PersistentCollection, then that thing's .equiv method is called when
testing with =. This makes sense, because all objects have a .equals
method, but only PCs have .equiv.
But if you wanted to compare a MetaConstant with, say, a hashmap (or
another MC), the runtime would not mess with the argument order.
--
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