mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
mruby-set: refactor internal methods for cleaner enumerable logic
Internal C functions now return a status, allowing Ruby methods to avoid `is_a?(Set)` checks and simplify the logic for handling different enumerable types. Co-authored-by: Gemini <gemini@google.com>
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user