Given a certain object that respond_to? :+ I would like to know what it’s the identity element for that operation on that object. For example, if a is Fixnum then it should give 0 for operation :+ because a + 0 == a for any Fixnum. Of course I already know the identity element for :+ and :* when talking about Fixnums, but is there any standard pattern/idiom to obtain those dynamically for all Numeric types and operations?.
More specifically I have write some code (see below) to calculate shortest path between v1 and v2 (vertexes in a graph) where the cost/distance/weigh of each edge in the graph is given in a user-specified type. In the current implementation the cost/weight of the edges could be a Fixnum, a Float or anything that implements Comparable and can add 0 to itself and return self.
But I was wondering what is the best pattern:
- requiring that type used must support
a + 0 == a - requiring that type provide some kind of addition identity element discovery ‘a.class::ADDITION_IDENTITY_ELEMENT
- ??
My Dijkstra algorithm implementation
def s_path(v1,v2)
dist = Hash.new { nil}
pred = {}
dist[v1] = 0 # distance from v1 to v1 is zero
#pq = nodes
pq = [v1]
while u = pq.shift
for edge in from(u)
u,v,cost = *edge
new_dist = cost + dist[u]
if dist[v].nil? or new_dist < dist[v]
dist[v] = new_dist
pred[v] = u
pq << v
end
end
end
path = [v2]
path << pred[path.last] while pred[path.last]
path.reverse
end
I think the
a.class::ADDITION_IDENTITY_ELEMENTis pretty good except I would call ita.class::Zero.Another option would be to do
(a-a).Personally I wouldn’t try to make things so abstract and I would just require that every distance be a
Numeric(e.g.FloatorInteger). Then you can just keep using0.