This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git i/hash.c w/hash.c | |
index 007508a..6f39e47 100644 | |
--- i/hash.c | |
+++ w/hash.c | |
@@ -2402,6 +2402,28 @@ rb_hash_flatten(int argc, VALUE *argv, VALUE hash) | |
return ary; | |
} | |
+static int | |
+hash_comprised_i(VALUE key, VALUE value, VALUE arg) | |
+{ | |
+ VALUE *args = (VALUE *)arg; | |
+ VALUE v = rb_hash_lookup2(args[0], key, Qundef); | |
+ if (v != Qundef && rb_equal(value, v)) return ST_CONTINUE; | |
+ args[1] = Qfalse; | |
+ return ST_STOP; | |
+} | |
+ | |
+static VALUE | |
+rb_hash_comprised_p(VALUE hash, VALUE other) | |
+{ | |
+ VALUE args[2]; | |
+ | |
+ other = to_hash(other); | |
+ args[0] = hash; | |
+ args[1] = Qtrue; | |
+ rb_hash_foreach(other, hash_comprised_i, (VALUE)args); | |
+ return args[1]; | |
+} | |
+ | |
static VALUE rb_hash_compare_by_id_p(VALUE hash); | |
/* | |
@@ -3626,6 +3648,27 @@ env_update(VALUE env, VALUE hash) | |
return env; | |
} | |
+static int | |
+env_comprised_i(VALUE key, VALUE value, VALUE arg) | |
+{ | |
+ VALUE *args = (VALUE *)arg; | |
+ VALUE v = rb_f_getenv(Qnil, key); | |
+ if (!NIL_P(v) && rb_equal(value, v)) return ST_CONTINUE; | |
+ args[0] = Qfalse; | |
+ return ST_STOP; | |
+} | |
+ | |
+static VALUE | |
+env_comprised_p(VALUE obj, VALUE other) | |
+{ | |
+ VALUE args[1]; | |
+ | |
+ other = to_hash(other); | |
+ args[0] = Qtrue; | |
+ rb_hash_foreach(other, env_comprised_i, (VALUE)args); | |
+ return args[0]; | |
+} | |
+ | |
/* | |
* A Hash is a dictionary-like collection of unique keys and their values. | |
* Also called associative arrays, they are similar to Arrays, but where an | |
@@ -3817,6 +3860,7 @@ Init_Hash(void) | |
rb_define_method(rb_cHash,"has_value?", rb_hash_has_value, 1); | |
rb_define_method(rb_cHash,"key?", rb_hash_has_key, 1); | |
rb_define_method(rb_cHash,"value?", rb_hash_has_value, 1); | |
+ rb_define_method(rb_cHash,"comprised?", rb_hash_comprised_p, 1); | |
rb_define_method(rb_cHash,"compare_by_identity", rb_hash_compare_by_id, 0); | |
rb_define_method(rb_cHash,"compare_by_identity?", rb_hash_compare_by_id_p, 0); | |
@@ -3876,6 +3920,7 @@ Init_Hash(void) | |
rb_define_singleton_method(envtbl,"to_h", env_to_hash, 0); | |
rb_define_singleton_method(envtbl,"assoc", env_assoc, 1); | |
rb_define_singleton_method(envtbl,"rassoc", env_rassoc, 1); | |
+ rb_define_singleton_method(envtbl,"comprised?", env_comprised_p, 1); | |
/* | |
* ENV is a Hash-like accessor for environment variables. |
I agree with @olivierlacan both that comprised?
has a different semantic meaning and that contain?
is better if include?
won't be changed to do this (instead of being an alias of has_key?
)
I'd be ok with contain
or contains
I'd say that #subset?
is a pretty accurate method name for this.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
As I mentioned to @hone02 yesterday, the word comprised (watch out, you named the file comprized) is probably not a good representation of this feature:
So in our case,
comprised_of?
would work better, but there's a show-stopper issue with the semantics: comprises seems to define an exhaustive list of components. By this I mean the following would be correct if we follow the English semantics of the verb:But in contrast the following wouldn't be correct because the arguments don't include *all the parts of the whole object being sent the message:
I still argue that
#contain?
is a better and semantically easier to understand, example: