From: Elias Athanasopoulos Date: 2004-04-16T02:50:06+09:00 Subject: Re: Hash, ==, key-value comparison On Fri, Apr 16, 2004 at 02:30:02AM +0900, walter@mwsewall.com wrote: > > > On Fri, Apr 16, 2004 at 02:04:10AM +0900, walter@mwsewall.com wrote: > > > Ok, > > ALthough the docs don't mention it, Hash comparison using == > > checks > not only the key value pairs, but also the default value / > > default > procs. > > So how does one compare 2 hashes key-value pairs. > > I can see that it > > > > I can contribute a patch to: > > > > * Change '==' method to compare only key-value pairs. > > * Add Hash#=== method to act like current Hash#== > > > > Comments? > > > > Personally, I like the idea. You get my vote! I will add a ChangeLog entry if it is accepted. elathan@velka:~/hacking/ruby> cat ../test.rb h1 = { "a" => 1, "b" => 2} h2 = Hash.new(2) h2["a"] = 1 h2["b"] = 2 puts h1 == h2 puts h1 === h2 elathan@velka:~/hacking/ruby> ./ruby ../test.rb true false Enjoy, -- University of Athens I bet the human brain Physics Department is a kludge --Marvin Minsky --- /home/elathan/hacking/ruby/hash.c.orig 2004-04-15 04:46:29.000000000 +0300 +++ /home/elathan/hacking/ruby/hash.c 2004-04-15 04:52:39.000000000 +0300 @@ -1425,6 +1425,48 @@ } if (RHASH(hash1)->tbl->num_entries != RHASH(hash2)->tbl->num_entries) return Qfalse; + + data.tbl = RHASH(hash2)->tbl; + data.result = Qtrue; + st_foreach(RHASH(hash1)->tbl, equal_i, (st_data_t)&data); + + return data.result; +} + +/* + * call-seq: + * hsh === other_hash => true or false + * + * Equality---Two hashes are strictly equal if they each contain the same number + * of keys and if each key-value pair is equal to (according to + * Object#==) the corresponding elements in the other + * hash. Both hashes must have also equal default values/procs. + * + * h1 = { "a" => 1, "c" => 2 } + * h2 = { 7 => 35, "c" => 2, "a" => 1 } + * h3 = { "a" => 1, "c" => 2, 7 => 35 } + * h4 = { "a" => 1, "d" => 2, "f" => 35 } + * h1 === h2 #=> false + * h2 === h3 #=> true + * h3 === h4 #=> false + * + */ + +static VALUE +rb_hash_strict_equal(hash1, hash2) + VALUE hash1, hash2; +{ + struct equal_data data; + + if (hash1 == hash2) return Qtrue; + if (TYPE(hash2) != T_HASH) { + if (!rb_respond_to(hash2, rb_intern("to_hash"))) { + return Qfalse; + } + return rb_equal(hash2, hash1); + } + if (RHASH(hash1)->tbl->num_entries != RHASH(hash2)->tbl->num_entries) + return Qfalse; if (!(rb_equal(RHASH(hash1)->ifnone, RHASH(hash2)->ifnone) && FL_TEST(hash1, HASH_PROC_DEFAULT) == FL_TEST(hash2, HASH_PROC_DEFAULT))) return Qfalse; @@ -1435,7 +1477,6 @@ return data.result; } - static int rb_hash_invert_i(key, value, hash) VALUE key, value; @@ -2365,6 +2406,7 @@ rb_define_method(rb_cHash,"inspect", rb_hash_inspect, 0); rb_define_method(rb_cHash,"==", rb_hash_equal, 1); + rb_define_method(rb_cHash,"===", rb_hash_strict_equal, 1); rb_define_method(rb_cHash,"[]", rb_hash_aref, 1); rb_define_method(rb_cHash,"fetch", rb_hash_fetch, -1); rb_define_method(rb_cHash,"[]=", rb_hash_aset, 2);