compare two identically hashes fails

  • Thread starter Simon Strandgaard
  • Start date
S

Simon Strandgaard

failure 1).. I compare 2 hashes with assert_equal.
If I inspect the hashes they appear to be identical.
But the == operator tells me they are different???
I only use Ruby's native types for the things stored in
the hash. Question: Why does this assertion fail ?



server> ruby test_all.rb
Loaded suite Unnamed TestSuite
Started
........................false
FF
Finished in 0.049179 seconds.

1) Failure!!!
test_one_letter(TestRegex) [./test_regex.rb:29]:
<{1=>[["a", 2]], 2=>[]}> expected but was
<{1=>[["a", 2]], 2=>[]}>

2) Failure!!!
test_sequence(TestRegex) [./test_regex.rb:36]:
<#<Nfa:0x81d2194 @nfa_hash={1=>[["a", 2]], 2=>[["b", 3]], 3=>[]}>> expected but was
<#<Nfa:0x81d225c @nfa_hash={1=>[["a", 2]], 2=>[["b", 3]], 3=>[]}>>

25 tests, 25 assertions, 2 failures, 0 errors
server>



In order to reproduce the problem, you can do a cvs-checkout of
these files.

cvs -d:pserver:[email protected]:/var/cvs/aeditor login

press enter when promped for a password

cvs -z3 -d:pserver:[email protected]:/var/cvs/aeditor co projects/experimental/nfa_to_dfa

cd projects/experimental/nfa_to_dfa

cvs up -r 1.2 nfa.rb
cvs up -r 1.2 regex.rb
cvs up -r 1.3 test_regex.rb


in order to execute it then do:

ruby test_regex.rb
 
S

Simon Strandgaard

failure 1).. I compare 2 hashes with assert_equal.
If I inspect the hashes they appear to be identical.
But the == operator tells me they are different???
I only use Ruby's native types for the things stored in
the hash. Question: Why does this assertion fail ?


I have found a simplification of my problem:

def test_hash_compare
on_new = proc {|h, k| h[k] = []}
h1 = Hash.new(&on_new)
h1[1] = [["a", 2]]
h1[2] = []
h2 = {1=>[["a", 2]], 2=>[]}
assert_equal(h1, h2)
end

How should I compare these 2 hashes, so it yields true ?
 
S

Simon Strandgaard

failure 1).. I compare 2 hashes with assert_equal.
If I inspect the hashes they appear to be identical.
But the == operator tells me they are different???
I only use Ruby's native types for the things stored in
the hash. Question: Why does this assertion fail ?


I have found a simplification of my problem:

def test_hash_compare
on_new = proc {|h, k| h[k] = []}
h1 = Hash.new(&on_new)
h1[1] = [["a", 2]]
h1[2] = []
h2 = {1=>[["a", 2]], 2=>[]}

h1.default = nil
h2.default = nil

assert_equal(h1, h2)
end

How should I compare these 2 hashes, so it yields true ?

Now it yields true.. thanks comp.lang.ruby :)
 
R

Robert Klemme

Simon Strandgaard said:
failure 1).. I compare 2 hashes with assert_equal.
If I inspect the hashes they appear to be identical.
But the == operator tells me they are different???
I only use Ruby's native types for the things stored in
the hash. Question: Why does this assertion fail ?


I have found a simplification of my problem:

def test_hash_compare
on_new = proc {|h, k| h[k] = []}
h1 = Hash.new(&on_new)
h1[1] = [["a", 2]]
h1[2] = []
h2 = {1=>[["a", 2]], 2=>[]}

h1.default = nil
h2.default = nil

assert_equal(h1, h2)
end

How should I compare these 2 hashes, so it yields true ?

Now it yields true.. thanks comp.lang.ruby :)

You're welcome. Sometimes expressing one's thoughts is already enough to
find the answer. :)

Have fun

robert
 
S

Simon Strandgaard

You're welcome. Sometimes expressing one's thoughts is already enough to
find the answer. :)

Yes.

Some more thoughs about Hash#default... here we go:


Why does Hash#inspect not output the content of Hash#default ?
It would make sense, because Ruby already compare Hash#default.




Why does Ruby not reset Hash#default when you issues a #to_hash ?
I think it would give a better behaiver? What does others thinks?

def test_hash_compare
on_new = proc {|h, k| h[k] = []}
h1 = Hash.new(&on_new)
h1[1] = [["a", 2]]
h1[2] = []
h2 = {1=>[["a", 2]], 2=>[]}
h1.default = nil # this is annoying!!
h2.default = nil # this is annoying!!
assert_equal(h1, h2)
end

If one instead could write it like following:

def test_hash_compare
on_new = proc {|h, k| h[k] = []}
h1 = Hash.new(&on_new)
h1[1] = [["a", 2]]
h1[2] = []
h2 = {1=>[["a", 2]], 2=>[]}
assert_equal(h1.to_hash, h2.to_hash)
end
 
R

Robert Klemme

Simon Strandgaard said:
Yes.

Some more thoughs about Hash#default... here we go:


Why does Hash#inspect not output the content of Hash#default ?
It would make sense, because Ruby already compare Hash#default.

In a way it would make sense. On the other hand, the inspect method
yields something that can be reconverted to a Hash using eval; although
this is likely to work only for standard types (String, Integer, Hash,
Array) the feature is quite useful. It would then be reasonable to change
the Hash creation syntax, maybe by allowing a single element in front:

a = {1=>2, 3=>4}
b = {nil 1=>2, 3=>4}
c = {"Foo" 1=>2, 3=>4}

a == b but a != c
Why does Ruby not reset Hash#default when you issues a #to_hash ?

Short answer: why should it?

Long answer: Because it returns self. That method is rather meant for
other types that can convert themselves to a hash. This method is not
expected to generate a side effect and the reset thus would violate POLS.

Kind regards

robert
 
K

Kent Dahl

Simon said:
Why does Hash#inspect not output the content of Hash#default ?
It would make sense, because Ruby already compare Hash#default.

Calling Hash#default may modify the Hash, such as with the proc you use.
(Try calling h1.default before assert_equal)

There are two values underlying the default, both a value default and a
proc default. Outputting them both would be ugly and visually
cluttering, IMHO.
Why does Ruby not reset Hash#default when you issues a #to_hash ?
I think it would give a better behaiver? What does others thinks?

I think it would break the protocol of the to_hash as a type conversion
method and result in information loss. What if someone calls to_hash
just to ensure they have a Hash or hash-like object? Why should the
default value or proc be tossed out?
def test_hash_compare
on_new = proc {|h, k| h[k] = []}
h1 = Hash.new(&on_new)
h1[1] = [["a", 2]]
h1[2] = []
h2 = {1=>[["a", 2]], 2=>[]}
h1.default = nil # this is annoying!!
h2.default = nil # this is annoying!!

That last line is not necessary, since the literal hash has nil as
default value anyway. So it is only half as annoying. :)
assert_equal(h1, h2)
end

If one instead could write it like following:

def test_hash_compare
on_new = proc {|h, k| h[k] = []}
h1 = Hash.new(&on_new)
h1[1] = [["a", 2]]
h1[2] = []

Just a tangential nitpick, but shouldn't the above line only be
h1[2]
if you're trying to exercise the on_new proc in the test?
h2 = {1=>[["a", 2]], 2=>[]}
assert_equal(h1.to_hash, h2.to_hash)
end

What I realized I missed upon seeing your question, was a
Hash#default_proc= method. It seems a bit restrictive to only be able to
set it on object construction. Does anyone know if there is a rationale
behind this decision?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,534
Members
45,007
Latest member
OrderFitnessKetoCapsules

Latest Threads

Top