From: Elias Athanasopoulos Date: 2004-04-19T19:32:07+09:00 Subject: Re: proposal Hash eql? , ==, === > I agree with both Hash#== and Hash#eql? But I'm not very positive elathan@testbed:~/hacking/ruby> cat ../test.rb h1 = Hash.new(42) h1["a"] = 1 h1["b"] = 2 h2 = { "a" => 1, "b" => 2 } puts h1 == h2 puts h1.eql?(h2) elathan@testbed:~/hacking/ruby> ./ruby ../test.rb true false --- hash.c.orig 2004-04-19 12:08:24.000000000 +0300 +++ hash.c 2004-04-19 12:21:06.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.eql? other_hash => true or false + * + * Strict 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 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.eql? h2 #=> false + * h2.eql? h3 #=> true + * h3.eql? 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; @@ -2365,6 +2407,8 @@ rb_define_method(rb_cHash,"inspect", rb_hash_inspect, 0); rb_define_method(rb_cHash,"==", rb_hash_equal, 1); + rb_define_method(rb_cHash,"eql?", rb_hash_strict_equal, 1); + rb_define_method(rb_cHash,"==", rb_hash_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);