Proposal Hash eql? , ==, ===

(Note: I sent a similar email last night in response to Matz, but
did not see it. I apologize if this is basically a duplicate.)

Hash#== should be for would be content equals and not
content and default value/proc equal. I think that most common case
for == would be content equality.

Hash#=== as Nobu pointed out === would make more sense to be a
membership test, i.e., alias for Hash#key?.

Hash.eql? should be content equal and default value/block (i.e what
the current == is now). There is some precedence for this in Numeric
where 1 == 1.0 is true but 1.eql?(1.0) is false. I see this as being
very similar circumstance.

Thanks for listening,

Walt

···

Walter Szewelanczyk
IS Director
M.W. Sewall & CO. email : walter@mwsewall.com
259 Front St. Phone : (207) 442-7994 x 128
Bath, ME 04530 Fax : (207) 443-6284


Hi,

···

In message “proposal Hash eql? , ==, ===” on 04/04/16, walter@mwsewall.com walter@mwsewall.com writes:

Hash#== should be for would be content equals and not
content and default value/proc equal. I think that most common case
for == would be content equality.

Hash#=== as Nobu pointed out === would make more sense to be a
membership test, i.e., alias for Hash#key?.

Hash.eql? should be content equal and default value/block (i.e what
the current == is now). There is some precedence for this in Numeric
where 1 == 1.0 is true but 1.eql?(1.0) is false. I see this as being
very similar circumstance.

I agree with both Hash#== and Hash#eql? But I’m not very positive
about making Hash#=== a membership test. Some usage of “===” are
membership, for example, Array and Class, but they are not general
consensus. I’m not sure how much useful that making === membership.

						matz.

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);