diff --git a/mrbgems/mruby-array-ext/mrblib/array.rb b/mrbgems/mruby-array-ext/mrblib/array.rb
index 5add0a5bd..0ff622774 100644
--- a/mrbgems/mruby-array-ext/mrblib/array.rb
+++ b/mrbgems/mruby-array-ext/mrblib/array.rb
@@ -700,35 +700,6 @@ class Array
self.replace(result)
end
- ##
- # call-seq:
- # ary.index(val) -> int or nil
- # ary.index {|item| block } -> int or nil
- #
- # Returns the _index_ of the first object in +ary+ such that the object is
- # == to +obj+.
- #
- # If a block is given instead of an argument, returns the _index_ of the
- # first object for which the block returns +true+. Returns +nil+ if no
- # match is found.
- #
- # ISO 15.2.12.5.14
- def index(val=NONE, &block)
- return to_enum(:find_index, val) if !block && NONE.equal?(val)
-
- if block
- idx = 0
- len = size
- while idx < len
- return idx if block.call self[idx]
- idx += 1
- end
- else
- return self.__ary_index(val)
- end
- nil
- end
-
##
# call-seq:
# ary.dig(idx, ...) -> object
diff --git a/mrbgems/mruby-array-ext/test/array.rb b/mrbgems/mruby-array-ext/test/array.rb
index bd7a2dc45..5197c8cd2 100644
--- a/mrbgems/mruby-array-ext/test/array.rb
+++ b/mrbgems/mruby-array-ext/test/array.rb
@@ -361,11 +361,6 @@ assert('Array#to_h') do
assert_raise(ArgumentError) { [[1]].to_h }
end
-assert("Array#index (block)") do
- assert_nil (1..10).to_a.index { |i| i % 5 == 0 and i % 7 == 0 }
- assert_equal 34, (1..100).to_a.index { |i| i % 5 == 0 and i % 7 == 0 }
-end
-
assert("Array#dig") do
h = [[[1]], 0]
assert_equal(1, h.dig(0, 0, 0))
diff --git a/src/array.c b/src/array.c
index 6319a10e4..21e7f5aa1 100644
--- a/src/array.c
+++ b/src/array.c
@@ -1133,31 +1133,84 @@ mrb_ary_last(mrb_state *mrb, mrb_value self)
return mrb_ary_new_from_values(mrb, size, ARY_PTR(a) + alen - size);
}
+/*
+ * call-seq:
+ * ary.index(val) -> int or nil
+ * ary.index {|item| block } -> int or nil
+ * array.index -> enumerator
+ *
+ * Returns the _index_ of the first object in +ary+ such that the object is
+ * == to +obj+.
+ *
+ * If a block is given instead of an argument, returns the _index_ of the
+ * first object for which the block returns +true+. Returns +nil+ if no
+ * match is found.
+ *
+ * ISO 15.2.12.5.14
+ */
static mrb_value
mrb_ary_index_m(mrb_state *mrb, mrb_value self)
{
- mrb_value obj = mrb_get_arg1(mrb);
+ mrb_value obj, blk;
- for (mrb_int i = 0; i < RARRAY_LEN(self); i++) {
- if (mrb_equal(mrb, RARRAY_PTR(self)[i], obj)) {
- return mrb_int_value(mrb, i);
+ if (mrb_get_args(mrb, "|o&", &obj, &blk) == 0 && mrb_nil_p(blk)) {
+ return mrb_funcall_id(mrb, self, MRB_SYM(to_enum), 1, mrb_symbol_value(MRB_SYM(index)));
+ }
+
+ if (mrb_nil_p(blk)) {
+ for (mrb_int i = 0; i < RARRAY_LEN(self); i++) {
+ if (mrb_equal(mrb, RARRAY_PTR(self)[i], obj)) {
+ return mrb_int_value(mrb, i);
+ }
+ }
+ }
+ else {
+ for (mrb_int i = 0; i < RARRAY_LEN(self); i++) {
+ mrb_value eq = mrb_funcall_id(mrb, blk, MRB_SYM(call), 1, RARRAY_PTR(self)[i]);
+ if (mrb_test(eq)) {
+ return mrb_int_value(mrb, i);
+ }
}
}
return mrb_nil_value();
}
+/*
+ * call-seq:
+ * ary.rindex(val) -> int or nil
+ * ary.rindex {|item| block } -> int or nil
+ * array.rindex -> enumerator
+ *
+ * Returns the _index_ of the first object in +ary+ such that the object is
+ * == to +obj+.
+ *
+ * If a block is given instead of an argument, returns the _index_ of the
+ * first object for which the block returns +true+. Returns +nil+ if no
+ * match is found.
+ *
+ * ISO 15.2.12.5.26
+ */
static mrb_value
mrb_ary_rindex_m(mrb_state *mrb, mrb_value self)
{
- mrb_value obj = mrb_get_arg1(mrb);
+ mrb_value obj, blk;
+
+ if (mrb_get_args(mrb, "|o&", &obj, &blk) == 0 && mrb_nil_p(blk)) {
+ return mrb_funcall_id(mrb, self, MRB_SYM(to_enum), 1, mrb_symbol_value(MRB_SYM(rindex)));
+ }
for (mrb_int i = RARRAY_LEN(self) - 1; i >= 0; i--) {
- mrb_int len;
-
- if (mrb_equal(mrb, RARRAY_PTR(self)[i], obj)) {
+ if (mrb_nil_p(blk)) {
+ if (mrb_equal(mrb, RARRAY_PTR(self)[i], obj)) {
return mrb_int_value(mrb, i);
+ }
}
- if (i > (len = RARRAY_LEN(self))) {
+ else {
+ mrb_value eq = mrb_funcall_id(mrb, blk, MRB_SYM(call), 1, RARRAY_PTR(self)[i]);
+ if (mrb_test(eq)) return mrb_int_value(mrb, i);
+ }
+ mrb_int len = RARRAY_LEN(self);
+ if (i > len) {
i = len;
}
}
@@ -1623,7 +1676,6 @@ mrb_init_array(mrb_state *mrb)
mrb_define_method_id(mrb, a, MRB_SYM(inspect), mrb_ary_to_s, MRB_ARGS_NONE());
mrb_define_method_id(mrb, a, MRB_SYM_B(sort), mrb_ary_sort_bang, MRB_ARGS_NONE());
- mrb_define_method_id(mrb, a, MRB_SYM(__ary_index), mrb_ary_index_m, MRB_ARGS_REQ(1)); /* kept for mruby-array-ext */
mrb_define_method_id(mrb, a, MRB_SYM(__delete), mrb_ary_delete, MRB_ARGS_REQ(1));
mrb_define_method_id(mrb, a, MRB_SYM(__svalue), mrb_ary_svalue, MRB_ARGS_NONE());
}
diff --git a/test/t/array.rb b/test/t/array.rb
index b40c03dd7..34b8aacbd 100644
--- a/test/t/array.rb
+++ b/test/t/array.rb
@@ -189,6 +189,11 @@ assert('Array#index', '15.2.12.5.14') do
assert_equal(nil, a.index(0))
end
+assert("Array#index (block)") do
+ assert_nil (1..10).to_a.index { |i| i % 5 == 0 and i % 7 == 0 }
+ assert_equal 34, (1..100).to_a.index { |i| i % 5 == 0 and i % 7 == 0 }
+end
+
assert('Array#initialize', '15.2.12.5.15') do
a = [].initialize(1)
b = [].initialize(2)
@@ -288,6 +293,11 @@ assert('Array#rindex', '15.2.12.5.26') do
assert_equal(nil, a.rindex(0))
end
+assert("Array#rindex (block)") do
+ assert_nil (1..10).to_a.rindex { |i| i % 5 == 0 and i % 7 == 0 }
+ assert_equal 69, (1..100).to_a.rindex { |i| i % 5 == 0 and i % 7 == 0 }
+end
+
assert('Array#shift', '15.2.12.5.27') do
a = [1,2,3]
b = a.shift