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 Edge
s. 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!