Hi,
I want to do something that may be impossible to do. It is not very important (I have possible workarounds), but I am curious…
I have a struct that represents an edge, defined as:
struct Edge{I<Integer}
e::Tuple{I,I}
p::I
r::Bool
end
The idea is that the actual edge is represented by the tuple e, whereas p and r are some attributes of the edge that are only relevant in some particular situations. I want to store Edges in a Set, but I want to be able to check set membership using only the tuple e. For this I redefine Base.hash, Base.isequal and Base.==:
import Base: hash, isequal, ==
hash(edge::Edge) = hash(edge.e)
isequal(e1::Edge,e2::Edge) = isequal(e1.e,e2.e)
==(e1::Edge,e2::Edge) = ==(e1.e,e2.e)
With this, I can do something like:
a = Edge((1,2),2,true); b = Edge((1,2),3,false); c = Edge((1,3),1,true);
S = Set([a,b,c])
(1,3) in S
and I get what I want. Namely: when constructing S, b replaces a since they are the same edge, and the answer to (1,3) in S is true. So far, so good.
However, in this way the attributes of the edges are inaccesible: I can check if the edge belongs to S but not what attributes are attached to it. Essentially, I cannot extract and Edge as it is stored in S. I can, for example, use pop!(S,m) where m is either a tuple or an Edge build from the tuple and default values for p and r. This removes the corresponding Edge from S, but the output is the same m that I used as key for popping, so the attributes of the previously stored edge are lost.
A simple solution is to use a dictionary instead of a set. In particular, a Dict{Tuple{I,I},Tuple{I,Bool}}, with the tuples as keys and the attributes as values. But in this way I essentially drop the data type Edge that is useful in other parts of the code.
It is not a great deal: I can keep Edge for the things it is useful, and just store my set of edges as a Dict instead of a real Set of Edges. But I wonder if there is some trick that I can apply for having my cake and eating it. In other words: Given a set where the hash applies not the whole element but only to a part, is it possible to retrieve the complete element?
Thanks!