I have a collection which contains a reference. The reference is generated by the called function. How can I compare the expected and actual collections given that the reference is different, even though the values are the same?
This is a special case of a more general problem. How can I perform a partial match, marking certain elements indicating that an exact match is unnecessary?
The point of this question is related to testing. I have a function returning a form containing references and I would like to compare it to see if it matches what I expect.
Based on comments:
I have done this...
(defprotocol Ireference? (reference? [this]))
(extend-type java.lang.Object Ireference? (reference? [this] false))
(extend-type nil Ireference? (reference? [this] false))
(extend-type clojure.lang.Ref Ireference? (reference? [this] true))
(extend-type clojure.lang.Agent Ireference? (reference? [this] true))
(defn ref->str
"takes an arbitrary tree and replaces all futures
with agnostic strings."
[form]
(clojure.walk/postwalk #(if (reference? %) (list 'ref @%) %) form))
Which does what I want.
(expect '{:foo (ref :bar) :baz {:zoo (ref :awk)}}
(ref->str {:foo (ref :bar) :baz {:zoo (ref :awk)}})
This gives me a match.
The reference? predicate is from How do we test whether something is a reference?
This, by design, cannot be done in clojure as you have described it. You can get a similar effect by walking the structure and calling deref
on all the mutable types to produce a value which can then be compared. As Rich Hickey explains nicely in this video (specifically 24 min in)
It doesn't make sense for two values to be equal only some of the time. If the language allowed this it would lose much of the power gained by focusing on programming with imitable values. Perhaps if you put the collection in the ref instead of the ref in the collection things would be easier to reason about?