Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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.
@olivierlacan

This comment has been minimized.

Copy link

olivierlacan commented May 1, 2014

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:

The members comprise the team
A team is comprised of its members.

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:

{ a: true, b: false, c: true }.comprised?([{ a:true }, { b: false }, { c: true}]) # => true

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:

{ a: true, b: false, c: true }.comprised?([{ a:true }]) # => false

I still argue that #contain? is a better and semantically easier to understand, example:

{ a: true, b: false, c: true }.contain?([{ a:true }]) # => true
@saturnflyer

This comment has been minimized.

Copy link

saturnflyer commented May 1, 2014

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

@hone

This comment has been minimized.

Copy link

hone commented May 2, 2014

I'd be ok with contain or contains

@evanphx

This comment has been minimized.

Copy link

evanphx commented Aug 28, 2014

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
You can’t perform that action at this time.