Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > How to make generic #== method?

Reply
Thread Tools

How to make generic #== method?

 
 
Lennon Day-Reynolds
Guest
Posts: n/a
 
      06-18-2004
> > 2) It doesn't work if the class has hash attribute because
> > {'a' => 1}.hash != {'a' => 1}.hash

>
> Now that is weird. I've a faint recollection of it being mentioned on
> ruby-talk before though, so perhaps its not a bug.


This makes sense, as both hashes are mutable. Their contents may be
the same, but they shouldn't be mistaken for the same object, as
either one's value could change at any time.

Consider the following:

---
h = Hash.new
g = Hash.new

hh = h.hash
gh = g.hash

puts "Hashes for 'h' and 'g' are " + (hh == gh ? "equal" : "not equal")

h[1] = true
g[1] = false

puts "Hash for 'h' has " + (hh == h.hash && "not ") + "changed"
puts "Hash for 'g' has " + (gh == g.hash && "not ") + "changed"
---

If you run the code above, the output should be:

---
Hashes for 'h' and 'g' are not equal
Hash for 'h' has not changed
Hash for 'g' has not changed
---

Using an object as a hash key, you want to check identity, not
equality. That way, even if your object is mutable, and you use it as
a key later, it will bee associated with the same value (assuming your
mapping hasn't changed, of course).

Lennon


 
Reply With Quote
 
 
 
 
Christoph
Guest
Posts: n/a
 
      06-18-2004
Zakaria wrote:
....
>
> URL? I know I'm lazy


Also checkout [ruby-talk :48114] (+ google) and
http://www.rubygarden.org/ruby?CompareByValue.

Personally I would tend to implement such a
class as a subclass of a Struct class ...

class LoopTag < Struct.new(aram,:contents)
def initialize(param)
super(param,[])
end
...
end


Just for the heck of it here is a cleaned up version
of the same problem I wrote two years ago, which is
sort (of) recursion and thread safe. There is an
obvious similarity to the idea of Joel content method
returning a Hash.


---
module CompareByValue
def ==(other)
if not instance_of?(other.class)
false
elsif equal?(other)
true
elsif id < other.id
CompareByValue.comp?(self,other)
else
CompareByValue.comp?(other,self)
end
end
end

class << CompareByValue
class Seen < Hash
Pair = Struct.new(:l,:r)

def initialize(l,r)
store(Pair.new(l.id,r.id),true)
end

def seen?(l,r)
self[Pair.new(l.id,r.id)]
end

def default(key)
store(key,true)
nil
end

def remove(l,r)
delete Pair.new(l.id,r.id)
end
end

# symbol mangling
SEEN_COMPS = "CBV#{id}_comps".intern
NUMS_CALLS = "CBV#{id}_calls".intern

def comp?(l,r)
return true if thread_local_seen?(l,r)
begin
Thread.current[NUMS_CALLS] +=1
return Comp.new.comp?(l,r)
rescue
Thread.current[SEEN_COMPS].remove(l,r)
raise
ensure
if (Thread.current[NUMS_CALLS] -= 1).zero?
Thread.current[SEEN_COMPS].clear
end
end
end

def thread_local_seen?(l,r)
unless comps = Thread.current[SEEN_COMPS]
Thread.current[NUMS_CALLS] = 0
Thread.current[SEEN_COMPS] = Seen.new(l,r)
false
else
comps.seen?(l,r)
end
end

class Comp < Hash
def comp?(l,r)
return true if l.equal?(r)
vars = l.instance_variables.sort!
return false unless vars == r.instance_variables.sort!

store(l.id,r.id)
vars.each do |name|
ll = l.instance_eval(name)
rr = r.instance_eval(name)
if CompareByValue === ll
return false unless ll.instance_of?(rr.class)
if rr_seen_id = self[ll.id]
return false unless rr_seen_id == rr.id
else
return false unless comp?(ll,rr)
end
else
return false unless ll == rr
end
end
return true
end
end
end
---

/Christoph
 
Reply With Quote
 
 
 
 
George Ogata
Guest
Posts: n/a
 
      06-19-2004
Lennon Day-Reynolds <> writes:

>> > 2) It doesn't work if the class has hash attribute because
>> > {'a' => 1}.hash != {'a' => 1}.hash

>>
>> Now that is weird. I've a faint recollection of it being mentioned on
>> ruby-talk before though, so perhaps its not a bug.

>
> This makes sense, as both hashes are mutable. Their contents may be
> the same, but they shouldn't be mistaken for the same object, as
> either one's value could change at any time.


So are Arrays and Strings (and plently else), but they can be hashed.
That's what the #rehash method is for, isn't it?

One possible reason I can think of is that the default_procs should
probably be compared too, but we can't compare procs in general.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: How include a large array? Edward A. Falk C Programming 1 04-04-2013 08:07 PM
not just generic type programming,but also parallism generic syntaxprogramming?? minlearn C++ 2 03-13-2009 05:17 PM
generic interfaces with generic methods Murat Tasan Java 1 02-03-2009 12:17 PM
Generic class in a non generic class nramnath@gmail.com Java 2 07-04-2006 07:24 AM
The best way to make a generic report page using a web service indicated in a xml file. Pablo Gutierrez ASP .Net 0 10-27-2003 11:03 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57