[DOC] Adds section "Hash Inclusion" (#12634)

This commit is contained in:
Burdette Lamar 2025-02-10 13:32:25 -06:00 committed by GitHub
parent 7fd589c7fc
commit b4bf3ed130
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
Notes: git 2025-02-10 19:32:42 +00:00
Merged-By: peterzhu2118 <peter@peterzhu.ca>
2 changed files with 113 additions and 38 deletions

31
doc/hash_inclusion.rdoc Normal file
View File

@ -0,0 +1,31 @@
== \Hash Inclusion
A hash is set-like in that it cannot have duplicate entries
(or even duplicate keys).
\Hash inclusion can therefore based on the idea of
{subset and superset}[https://en.wikipedia.org/wiki/Subset].
Two hashes may be tested for inclusion,
based on comparisons of their entries.
An entry <tt>h0[k0]</tt> in one hash
is equal to an entry <tt>h1[k1]</tt> in another hash
if and only if the two keys are equal (<tt>k0 == k1</tt>)
and their two values are equal (<tt>h0[k0] == h1[h1]</tt>).
A hash may be a subset or a superset of another hash:
- Subset (included in or equal to another):
- \Hash +h0+ is a _subset_ of hash +h1+ (see Hash#<=)
if each entry in +h0+ is equal to an entry in +h1+.
- Further, +h0+ is a <i>proper subset</i> of +h1+ (see Hash#<)
if +h1+ is larger than +h0+.
- Superset (including or equal to another):
- \Hash +h0+ is a _superset_ of hash +h1+ (see Hash#>=)
if each entry in +h1+ is equal to an entry in +h0+.
- Further, +h0+ is a <i>proper superset</i> of +h1+ (see Hash#>)
if +h0+ is larger than +h1+.

120
hash.c
View File

@ -3803,21 +3803,29 @@ hash_equal(VALUE hash1, VALUE hash2, int eql)
/* /*
* call-seq: * call-seq:
* hash == object -> true or false * self == object -> true or false
*
* Returns whether +self+ and +object+ are equal.
* *
* Returns +true+ if all of the following are true: * Returns +true+ if all of the following are true:
* * +object+ is a +Hash+ object. *
* * +hash+ and +object+ have the same keys (regardless of order). * - +object+ is a +Hash+ object (or can be converted to one).
* * For each key +key+, <tt>hash[key] == object[key]</tt>. * - +self+ and +object+ have the same keys (regardless of order).
* - For each key +key+, <tt>self[key] == object[key]</tt>.
* *
* Otherwise, returns +false+. * Otherwise, returns +false+.
* *
* Equal: * Examples:
* h1 = {foo: 0, bar: 1, baz: 2} *
* h2 = {foo: 0, bar: 1, baz: 2} * h = {foo: 0, bar: 1}
* h1 == h2 # => true * h == {foo: 0, bar: 1} # => true # Equal entries (same order)
* h3 = {baz: 2, bar: 1, foo: 0} * h == {bar: 1, foo: 0} # => true # Equal entries (different order).
* h1 == h3 # => true * h == 1 # => false # Object not a hash.
* h == {} # => false # Different number of entries.
* h == {foo: 0, bar: 1} # => false # Different key.
* h == {foo: 0, bar: 1} # => false # Different value.
*
* Related: see {Methods for Comparing}[rdoc-ref:Hash@Methods+for+Comparing].
*/ */
static VALUE static VALUE
@ -4640,14 +4648,22 @@ hash_le(VALUE hash1, VALUE hash2)
/* /*
* call-seq: * call-seq:
* hash <= other_hash -> true or false * self <= other_hash -> true or false
* *
* Returns +true+ if +hash+ is a subset of +other_hash+, +false+ otherwise: * Returns +true+ if the entries of +self+ are a subset of the entries of +other_hash+,
* h1 = {foo: 0, bar: 1} * +false+ otherwise:
* h2 = {foo: 0, bar: 1, baz: 2} *
* h1 <= h2 # => true * h0 = {foo: 0, bar: 1}
* h2 <= h1 # => false * h1 = {foo: 0, bar: 1, baz: 2}
* h1 <= h1 # => true * h0 <= h0 # => true
* h0 <= h1 # => true
* h1 <= h0 # => false
*
* See {Hash Inclusion}[rdoc-ref:hash_inclusion.rdoc].
*
* Raises TypeError if +other_hash+ is not a hash and cannot be converted to a hash.
*
* Related: see {Methods for Comparing}[rdoc-ref:Hash@Methods+for+Comparing].
*/ */
static VALUE static VALUE
rb_hash_le(VALUE hash, VALUE other) rb_hash_le(VALUE hash, VALUE other)
@ -4659,14 +4675,24 @@ rb_hash_le(VALUE hash, VALUE other)
/* /*
* call-seq: * call-seq:
* hash < other_hash -> true or false * self < other_hash -> true or false
* *
* Returns +true+ if +hash+ is a proper subset of +other_hash+, +false+ otherwise: * Returns +true+ if the entries of +self+ are a proper subset of the entries of +other_hash+,
* h1 = {foo: 0, bar: 1} * +false+ otherwise:
* h2 = {foo: 0, bar: 1, baz: 2} *
* h1 < h2 # => true * h = {foo: 0, bar: 1}
* h2 < h1 # => false * h < {foo: 0, bar: 1, baz: 2} # => true # Proper subset.
* h1 < h1 # => false * h < {baz: 2, bar: 1, foo: 0} # => true # Order may differ.
* h < h # => false # Not a proper subset.
* h < {bar: 1, foo: 0} # => false # Not a proper subset.
* h < {foo: 0, bar: 1, baz: 2} # => false # Different key.
* h < {foo: 0, bar: 1, baz: 2} # => false # Different value.
*
* See {Hash Inclusion}[rdoc-ref:hash_inclusion.rdoc].
*
* Raises TypeError if +other_hash+ is not a hash and cannot be converted to a hash.
*
* Related: see {Methods for Comparing}[rdoc-ref:Hash@Methods+for+Comparing].
*/ */
static VALUE static VALUE
rb_hash_lt(VALUE hash, VALUE other) rb_hash_lt(VALUE hash, VALUE other)
@ -4678,14 +4704,22 @@ rb_hash_lt(VALUE hash, VALUE other)
/* /*
* call-seq: * call-seq:
* hash >= other_hash -> true or false * self >= other_hash -> true or false
* *
* Returns +true+ if +hash+ is a superset of +other_hash+, +false+ otherwise: * Returns +true+ if the entries of +self+ are a superset of the entries of +other_hash+,
* h1 = {foo: 0, bar: 1, baz: 2} * +false+ otherwise:
* h2 = {foo: 0, bar: 1} *
* h1 >= h2 # => true * h0 = {foo: 0, bar: 1, baz: 2}
* h2 >= h1 # => false * h1 = {foo: 0, bar: 1}
* h1 >= h1 # => true * h0 >= h1 # => true
* h0 >= h0 # => true
* h1 >= h0 # => false
*
* See {Hash Inclusion}[rdoc-ref:hash_inclusion.rdoc].
*
* Raises TypeError if +other_hash+ is not a hash and cannot be converted to a hash.
*
* Related: see {Methods for Comparing}[rdoc-ref:Hash@Methods+for+Comparing].
*/ */
static VALUE static VALUE
rb_hash_ge(VALUE hash, VALUE other) rb_hash_ge(VALUE hash, VALUE other)
@ -4697,14 +4731,24 @@ rb_hash_ge(VALUE hash, VALUE other)
/* /*
* call-seq: * call-seq:
* hash > other_hash -> true or false * self > other_hash -> true or false
* *
* Returns +true+ if +hash+ is a proper superset of +other_hash+, +false+ otherwise: * Returns +true+ if the entries of +self+ are a proper superset of the entries of +other_hash+,
* h1 = {foo: 0, bar: 1, baz: 2} * +false+ otherwise:
* h2 = {foo: 0, bar: 1} *
* h1 > h2 # => true * h = {foo: 0, bar: 1, baz: 2}
* h2 > h1 # => false * h > {foo: 0, bar: 1} # => true # Proper superset.
* h1 > h1 # => false * h > {bar: 1, foo: 0} # => true # Order may differ.
* h > h # => false # Not a proper superset.
* h > {baz: 2, bar: 1, foo: 0} # => false # Not a proper superset.
* h > {foo: 0, bar: 1} # => false # Different key.
* h > {foo: 0, bar: 1} # => false # Different value.
*
* See {Hash Inclusion}[rdoc-ref:hash_inclusion.rdoc].
*
* Raises TypeError if +other_hash+ is not a hash and cannot be converted to a hash.
*
* Related: see {Methods for Comparing}[rdoc-ref:Hash@Methods+for+Comparing].
*/ */
static VALUE static VALUE
rb_hash_gt(VALUE hash, VALUE other) rb_hash_gt(VALUE hash, VALUE other)