mruby-array-ext: add Array#deconstruct for pattern matching

Implement new method for Ruby 2.7+ pattern matching compatibility.
Returns the array itself to enable case/in pattern matching syntax.
Complements Hash#deconstruct_keys for complete pattern matching support.

Co-authored-by: Atlassian Rovo Dev
This commit is contained in:
Yukihiro "Matz" Matsumoto
2025-07-01 20:44:04 +09:00
parent 6e79fed77b
commit 69d278589d
2 changed files with 52 additions and 0 deletions
+26
View File
@@ -1261,6 +1261,31 @@ ary_insert(mrb_state *mrb, mrb_value self)
return self;
}
/*
* call-seq:
* ary.deconstruct -> ary
*
* Returns the array itself for pattern matching.
*
* This method is used by pattern matching to deconstruct arrays.
* It simply returns the array itself, allowing pattern matching
* to work with array elements.
*
* a = [1, 2, 3]
* a.deconstruct #=> [1, 2, 3]
*
* Pattern matching usage:
* case [1, 2, 3]
* in [x, y, z]
* # x=1, y=2, z=3
* end
*/
static mrb_value
ary_deconstruct(mrb_state *mrb, mrb_value ary)
{
return ary;
}
void
mrb_mruby_array_ext_gem_init(mrb_state* mrb)
{
@@ -1291,6 +1316,7 @@ mrb_mruby_array_ext_gem_init(mrb_state* mrb)
mrb_define_method_id(mrb, a, MRB_SYM(__normalize_index), ary_normalize_index, MRB_ARGS_REQ(1));
mrb_define_method_id(mrb, a, MRB_SYM(__fetch), ary_fetch, MRB_ARGS_REQ(3));
mrb_define_method_id(mrb, a, MRB_SYM(insert), ary_insert, MRB_ARGS_ARG(1, -1));
mrb_define_method_id(mrb, a, MRB_SYM(deconstruct), ary_deconstruct, MRB_ARGS_NONE());
}
void
+26
View File
@@ -757,3 +757,29 @@ assert("Array#repeated_permutation") do
assert_repeated_permutation([[]], a, 0)
assert_repeated_permutation([], a, -1)
end
assert("Array#deconstruct") do
# Basic functionality - returns self
a = [1, 2, 3]
result = a.deconstruct
assert_equal([1, 2, 3], result)
assert_true(result.equal?(a))
# Empty array
b = []
result_empty = b.deconstruct
assert_equal([], result_empty)
assert_true(result_empty.equal?(b))
# Mixed types
c = [1, "hello", :symbol, nil, true]
result_mixed = c.deconstruct
assert_equal([1, "hello", :symbol, nil, true], result_mixed)
assert_true(result_mixed.equal?(c))
# Nested arrays
d = [[1, 2], [3, 4], [5]]
result_nested = d.deconstruct
assert_equal([[1, 2], [3, 4], [5]], result_nested)
assert_true(result_nested.equal?(d))
end