diff --git a/mrbgems/mruby-set/mrblib/set.rb b/mrbgems/mruby-set/mrblib/set.rb index 91f2f852e..4858331a7 100644 --- a/mrbgems/mruby-set/mrblib/set.rb +++ b/mrbgems/mruby-set/mrblib/set.rb @@ -26,14 +26,10 @@ class Set # @param [Enumerable] enum The enumerable object to merge elements from # @return [Set] self def merge(enum) - if enum.is_a?(Set) - # Fast path: Call C-implemented function for Set-to-Set merge - __merge(enum) - else - # General path: Add each element from the enumerable - __do_with_enum(enum) { add(_1) } - self + unless __merge(enum) + __do_with_enum(enum) { |o| add(o) } end + self end # Replaces the contents of the set with the contents of the given enumerable @@ -52,14 +48,10 @@ class Set # @param [Enumerable] enum The enumerable object containing elements to remove # @return [Set] self def subtract(enum) - if enum.is_a?(Set) - # Fast path: Call C-implemented function for Set-to-Set subtraction - __subtract(enum) - else - # General path: Remove each element from the enumerable - __do_with_enum(enum) { delete(_1) } - self + unless __subtract(enum) + __do_with_enum(enum) { |o| delete(o) } end + self end # Returns a new set containing elements common to the set and the given @@ -68,15 +60,12 @@ class Set # @param [Enumerable] enum The enumerable object to find common elements with # @return [Set] A new set containing elements common to both def intersection(enum) - if enum.is_a?(Set) - # Fast path: Call C-implemented function for Set-to-Set intersection - __intersection(enum) - else - # General path: Implement in Ruby for any enumerable - n = Set.new - __do_with_enum(enum) { n.add(_1) if include?(_1) } - n - end + n = __intersection(enum) + return n if n + + n = Set.new + __do_with_enum(enum) { |o| n.add(o) if include?(o) } + n end # Alias for #intersection @@ -88,13 +77,10 @@ class Set # @param [Enumerable] enum The enumerable object to merge with # @return [Set] A new set containing all elements from both def union(enum) - if enum.is_a?(Set) - # Fast path: Call C-implemented function for Set-to-Set union - __union(enum) - else - # General path: Create a duplicate and merge the enumerable - dup.merge(enum) - end + n = __union(enum) + return n if n + + dup.merge(enum) end # Aliases for #union @@ -107,15 +93,12 @@ class Set # @param [Enumerable] enum The enumerable object to find elements to remove # @return [Set] A new set with elements from self that are not in enum def difference(enum) - if enum.is_a?(Set) - # Fast path: Call C-implemented function for Set-to-Set difference - __difference(enum) - else - # General path: Create a duplicate and remove the enumerable elements - result = dup - __do_with_enum(enum) { result.delete(_1) } - result - end + n = __difference(enum) + return n if n + + result = dup + __do_with_enum(enum) { |o| result.delete(o) } + result end # Alias for #difference @@ -127,14 +110,11 @@ class Set # @param [Enumerable] enum The enumerable object to find exclusive elements with # @return [Set] A new set containing elements exclusive between both def ^(enum) - if enum.is_a?(Set) - # Fast path: Call C-implemented function for Set-to-Set XOR - __xor(enum) - else - # General path: Convert enum to a set and calculate (self|s2)-(self&s2) - s2 = Set.new(enum) - (self | s2) - (self & s2) - end + n = __xor(enum) + return n if n + + s2 = Set.new(enum) + (self | s2) - (self & s2) end # Iterates over each element in the set. diff --git a/mrbgems/mruby-set/src/set.c b/mrbgems/mruby-set/src/set.c index b77be099c..d9556f2cb 100644 --- a/mrbgems/mruby-set/src/set.c +++ b/mrbgems/mruby-set/src/set.c @@ -672,6 +672,11 @@ static mrb_value set_core_merge(mrb_state *mrb, mrb_value self) { mrb_value other = mrb_get_arg1(mrb); + + if (!set_is_set(other)) { + return mrb_false_value(); + } + kset_t *self_set = set_get_kset(mrb, self); kset_t *other_set = set_get_kset(mrb, other); @@ -680,7 +685,7 @@ set_core_merge(mrb_state *mrb, mrb_value self) kset_copy_elements(mrb, self_set, other_set); } - return self; + return mrb_true_value(); } /* @@ -692,11 +697,15 @@ set_core_subtract(mrb_state *mrb, mrb_value self) { mrb_value other = mrb_get_arg1(mrb); + if (!set_is_set(other)) { + return mrb_false_value(); + } + kset_t *self_set = set_get_kset(mrb, self); - if (kset_is_empty(self_set)) return self; + if (kset_is_empty(self_set)) return mrb_true_value(); kset_t *other_set = set_get_kset(mrb, other); - if (kset_is_empty(other_set)) return self; + if (kset_is_empty(other_set)) return mrb_true_value(); /* Remove all elements that are in other set */ KSET_FOREACH(other_set, k) { @@ -707,7 +716,7 @@ set_core_subtract(mrb_state *mrb, mrb_value self) } } - return self; + return mrb_true_value(); } /* @@ -719,6 +728,10 @@ set_core_union(mrb_state *mrb, mrb_value self) { mrb_value other = mrb_get_arg1(mrb); + if (!set_is_set(other)) { + return mrb_nil_value(); + } + /* Create a new set by duplicating self */ mrb_value result = mrb_obj_dup(mrb, self); kset_t *result_set = set_get_kset(mrb, result); @@ -745,6 +758,10 @@ set_core_difference(mrb_state *mrb, mrb_value self) { mrb_value other = mrb_get_arg1(mrb); + if (!set_is_set(other)) { + return mrb_nil_value(); + } + /* Create a new set by duplicating self */ mrb_value result = mrb_obj_dup(mrb, self); kset_t *result_set = set_get_kset(mrb, result); @@ -778,6 +795,10 @@ set_core_intersection(mrb_state *mrb, mrb_value self) { mrb_value other = mrb_get_arg1(mrb); + if (!set_is_set(other)) { + return mrb_nil_value(); + } + /* Create a new empty set of the same class as self */ mrb_value result = mrb_obj_new(mrb, mrb_obj_class(mrb, self), 0, NULL); kset_t *result_set = set_get_kset(mrb, result); @@ -810,6 +831,11 @@ static mrb_value set_core_xor(mrb_state *mrb, mrb_value self) { mrb_value other = mrb_get_arg1(mrb); + + if (!set_is_set(other)) { + return mrb_nil_value(); + } + mrb_value result = mrb_obj_new(mrb, mrb_obj_class(mrb, self), 0, NULL); kset_t *result_set = set_get_kset(mrb, result); kset_t *self_set, *other_set;