diff --git a/array.c b/array.c
index 6b551dbe246c1f..49b01881281693 100644
--- a/array.c
+++ b/array.c
@@ -26,7 +26,9 @@
VALUE rb_cArray;
-static ID id_cmp, id_div, id_power;
+static ID id_cmp, id_div, id_power, id_call;
+
+#define id_eqq idEqq
#define ARY_DEFAULT_SIZE 16
#define ARY_MAX_SIZE (LONG_MAX / (int)sizeof(VALUE))
@@ -3833,6 +3835,7 @@ rb_ary_hash(VALUE ary)
/*
* call-seq:
* ary.include?(object) -> true or false
+ * ary.member?(object) -> true or false
*
* Returns +true+ if the given +object+ is present in +self+ (that is, if any
* element == +object+), otherwise returns +false+.
@@ -5407,6 +5410,318 @@ rb_ary_drop_while(VALUE ary)
return rb_ary_drop(ary, LONG2FIX(i));
}
+/*
+ * call-seq:
+ * ary.each_with_index(*args) { |obj, i| block } -> ary
+ * ary.each_with_index(*args) -> an_enumerator
+ *
+ * See also Enumerable#each_with_index
+ */
+VALUE
+rb_ary_each_with_index(int argc, VALUE *argv, VALUE array)
+{
+ long i;
+ volatile VALUE ary = array;
+
+ RETURN_SIZED_ENUMERATOR(ary, argc, argv, ary_enum_length);
+ for (i=0; i obj
+ * ary.each_with_object(obj) -> an_enumerator
+ *
+ * See also Enumerable#each_with_object
+ */
+VALUE
+rb_ary_each_with_object(VALUE array, VALUE memo)
+{
+ long i;
+ volatile VALUE ary = array;
+
+ RETURN_SIZED_ENUMERATOR(ary, 1, &memo, ary_enum_length);
+ for (i=0; i obj
+ * ary.inject(sym) -> obj
+ * ary.inject(initial) { |memo, obj| block } -> obj
+ * ary.inject { |memo, obj| block } -> obj
+ * ary.reduce(initial, sym) -> obj
+ * ary.reduce(sym) -> obj
+ * ary.reduce(initial) { |memo, obj| block } -> obj
+ * ary.reduce { |memo, obj| block } -> obj
+ *
+ * See also Enumerable#inject
+ */
+static VALUE
+rb_ary_inject(int argc, VALUE *argv, VALUE array)
+{
+ ID id;
+ VALUE op, init = Qnil;
+ volatile VALUE ary = array;
+ long i = 0;
+ long len = RARRAY_LEN(ary);
+ int n = rb_scan_args(argc, argv, "02", &init, &op);
+
+ if (n == 0 || n == 1 && rb_block_given_p()) {
+ if (!len) return init;
+ if (!argc) {
+ init = RARRAY_AREF(ary, 0);
+ ++i;
+ }
+ for (; i < RARRAY_LEN(ary); ++i) {
+ init = rb_yield_values(2, init, RARRAY_AREF(ary, i));
+ }
+ return init;
+ }
+ switch (n) {
+ case 1:
+ id = rb_check_id(&init);
+ op = id ? ID2SYM(id) : init;
+ argc = 0;
+ init = Qnil;
+ break;
+ case 2:
+ if (rb_block_given_p()) {
+ rb_warning("given block not used");
+ }
+ id = rb_check_id(&op);
+ if (id) op = ID2SYM(id);
+ break;
+ }
+ if (!len) return init;
+ if (!argc) {
+ init = RARRAY_AREF(ary, 0);
+ ++i;
+ }
+ for (; i < RARRAY_LEN(ary); ++i) {
+ if (SYMBOL_P(op)) {
+ init = rb_funcall(init, SYM2ID(op), 1, RARRAY_AREF(ary, i));
+ }
+ else {
+ VALUE args[2];
+ args[0] = op;
+ args[1] = RARRAY_AREF(ary, i);
+ init = rb_f_send(numberof(args), args, init);
+ }
+ }
+ return init;
+}
+
+/*
+ * call-seq:
+ * ary.flat_map { |obj| block } -> array
+ * ary.collect_concat { |obj| block } -> array
+ * ary.flat_map -> an_enumerator
+ * ary.collect_concat -> an_enumerator
+ *
+ * See also Enumerable#flat_map
+ */
+static VALUE
+rb_ary_flat_map(VALUE ary)
+{
+ long i;
+ VALUE obj, tmp, result;
+
+ RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
+
+ result = rb_ary_new();
+ for (i = 0; i < RARRAY_LEN(ary); ++i) {
+ obj = rb_yield(RARRAY_AREF(ary, i));
+ tmp = rb_check_array_type(obj);
+ if (NIL_P(obj)) {
+ rb_ary_push(result, obj);
+ }
+ else {
+ rb_ary_concat(result, tmp);
+ }
+ }
+
+ return result;
+}
+
+/*
+ * call-seq:
+ * ary.grep(pattern) -> array
+ * ary.grep(pattern) { |obj| block } -> array
+ *
+ * See also Enumerable#grep
+ */
+static VALUE
+rb_ary_grep(VALUE ary, VALUE pat)
+{
+ long i, len = RARRAY_LEN(ary);
+ const VALUE *ptr = RARRAY_CONST_PTR(ary);
+ VALUE obj, result = rb_ary_new();
+
+ if (!len) return result;
+ if (!rb_block_given_p()) {
+ for (i = 0; i < len; ++i) {
+ if (RTEST(rb_funcall(pat, id_eqq, 1, ptr[i]))) {
+ rb_ary_push(result, ptr[i]);
+ }
+ }
+ }
+ else {
+ for (i = 0; i < RARRAY_LEN(ary); ++i) {
+ obj = RARRAY_AREF(ary, i);
+ if (RTEST(rb_funcall(pat, id_eqq, 1, obj))) {
+ rb_ary_push(result, rb_yield(obj));
+ }
+ }
+ }
+
+ return result;
+}
+
+/*
+ * call-seq:
+ * ary.partition { |obj| block } -> [ true_array, false_array ]
+ * ary.partition -> an_enumerator
+ *
+ * See also Enumerable#partition
+ */
+static VALUE
+rb_ary_partition(VALUE ary)
+{
+ long i;
+ VALUE false_array, true_array, obj;
+ RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
+
+ false_array = rb_ary_new();
+ true_array = rb_ary_new();
+ for (i = 0; i < RARRAY_LEN(ary); ++i) {
+ obj = RARRAY_AREF(ary, i);
+ if (RTEST(rb_yield(obj))) {
+ rb_ary_push(true_array, obj);
+ }
+ else {
+ rb_ary_push(false_array, obj);
+ }
+ }
+
+ return rb_assoc_new(true_array, false_array);
+}
+
+/*
+ * call-seq:
+ * ary.detect(ifnone = nil) { |obj| block } -> obj or nil
+ * ary.find(ifnone = nil) { |obj| block } -> obj or nil
+ * ary.detect(ifnone = nil) -> an_enumerator
+ * ary.find(ifnone = nil) -> an_enumerator
+ *
+ * See also Enumerable#find
+ */
+static VALUE
+rb_ary_find(int argc, VALUE *argv, VALUE ary)
+{
+ long i;
+ VALUE obj, if_none;
+
+ rb_scan_args(argc, argv, "01", &if_none);
+ RETURN_ENUMERATOR(ary, argc, argv);
+ for (i = 0; i < RARRAY_LEN(ary); ++i) {
+ obj = RARRAY_AREF(ary, i);
+ if (RTEST(rb_yield(obj))) return obj;
+ }
+ if (!NIL_P(if_none)) {
+ return rb_funcall(if_none, id_call, 0, 0);
+ }
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * ary.one? [{ |obj| block }] -> true or false
+ *
+ * See also Enumerable#one?
+ */
+static VALUE
+rb_ary_one_p(VALUE ary)
+{
+ long i, len = RARRAY_LEN(ary);
+ const VALUE *ptr = RARRAY_CONST_PTR(ary);
+ VALUE result = Qundef;
+
+ if (!len) return Qfalse;
+ if (!rb_block_given_p()) {
+ for (i = 0; i < len; ++i) {
+ if (RTEST(ptr[i])) {
+ if (result == Qundef) result = Qtrue;
+ else if (result == Qtrue) return Qfalse;
+ }
+ }
+ }
+ else {
+ for (i = 0; i < RARRAY_LEN(ary); ++i) {
+ if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
+ if (result == Qundef) result = Qtrue;
+ else if (result == Qtrue) return Qfalse;
+ }
+ }
+ }
+ if (result == Qundef) return Qfalse;
+ return result;
+}
+
+/*
+ * call-seq:
+ * ary.none? [{ |obj| block }] -> true or false
+ *
+ * See also Enumerable#none?
+ */
+static VALUE
+rb_ary_none_p(VALUE ary)
+{
+ long i, len = RARRAY_LEN(ary);
+ const VALUE *ptr = RARRAY_CONST_PTR(ary);
+
+ if (!len) return Qtrue;
+ if (!rb_block_given_p()) {
+ for (i = 0; i < len; ++i) if (RTEST(ptr[i])) return Qfalse;
+ }
+ else {
+ for (i = 0; i < RARRAY_LEN(ary); ++i) {
+ if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qfalse;
+ }
+ }
+ return Qtrue;
+}
+
+/*
+ * call-seq:
+ * ary.all? [{ |obj| block } ] -> true or false
+ *
+ * See also Enumerable#all?
+ */
+static VALUE
+rb_ary_all_p(VALUE ary)
+{
+ long i, len = RARRAY_LEN(ary);
+ const VALUE *ptr = RARRAY_CONST_PTR(ary);
+
+ if (!len) return Qtrue;
+ if (!rb_block_given_p()) {
+ for (i = 0; i < len; ++i) if (!RTEST(ptr[i])) return Qfalse;
+ }
+ else {
+ for (i = 0; i < RARRAY_LEN(ary); ++i) {
+ if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qfalse;
+ }
+ }
+ return Qtrue;
+}
+
/*
* call-seq:
* ary.any? [{ |obj| block }] -> true or false
@@ -5687,6 +6002,7 @@ Init_Array(void)
rb_define_method(rb_cArray, "inspect", rb_ary_inspect, 0);
rb_define_alias(rb_cArray, "to_s", "inspect");
rb_define_method(rb_cArray, "to_a", rb_ary_to_a, 0);
+ rb_define_method(rb_cArray, "entries", rb_ary_to_a, 0);
rb_define_method(rb_cArray, "to_h", rb_ary_to_h, 0);
rb_define_method(rb_cArray, "to_ary", rb_ary_to_ary_m, 0);
rb_define_method(rb_cArray, "frozen?", rb_ary_frozen_p, 0);
@@ -5729,6 +6045,7 @@ Init_Array(void)
rb_define_method(rb_cArray, "collect!", rb_ary_collect_bang, 0);
rb_define_method(rb_cArray, "map", rb_ary_collect, 0);
rb_define_method(rb_cArray, "map!", rb_ary_collect_bang, 0);
+ rb_define_method(rb_cArray, "find_all", rb_ary_select, 0);
rb_define_method(rb_cArray, "select", rb_ary_select, 0);
rb_define_method(rb_cArray, "select!", rb_ary_select_bang, 0);
rb_define_method(rb_cArray, "keep_if", rb_ary_keep_if, 0);
@@ -5744,6 +6061,7 @@ Init_Array(void)
rb_define_method(rb_cArray, "clear", rb_ary_clear, 0);
rb_define_method(rb_cArray, "fill", rb_ary_fill, -1);
rb_define_method(rb_cArray, "include?", rb_ary_includes, 1);
+ rb_define_method(rb_cArray, "member?", rb_ary_includes, 1);
rb_define_method(rb_cArray, "<=>", rb_ary_cmp, 1);
rb_define_method(rb_cArray, "slice", rb_ary_aref, -1);
@@ -5783,8 +6101,23 @@ Init_Array(void)
rb_define_method(rb_cArray, "bsearch", rb_ary_bsearch, 0);
rb_define_method(rb_cArray, "any?", rb_ary_any_p, 0);
+ rb_define_method(rb_cArray, "all?", rb_ary_all_p, 0);
+ rb_define_method(rb_cArray, "one?", rb_ary_one_p, 0);
+ rb_define_method(rb_cArray, "none?", rb_ary_none_p, 0);
+ rb_define_method(rb_cArray, "find", rb_ary_find, -1);
+ rb_define_method(rb_cArray, "detect", rb_ary_find, -1);
+ rb_define_method(rb_cArray, "inject", rb_ary_inject, -1);
+ rb_define_method(rb_cArray, "reduce", rb_ary_inject, -1);
+ rb_define_method(rb_cArray, "each_with_index", rb_ary_each_with_index, -1);
+ rb_define_method(rb_cArray, "each_with_object", rb_ary_each_with_object, 1);
+ rb_define_method(rb_cArray, "partition", rb_ary_partition, 0);
+ rb_define_method(rb_cArray, "grep", rb_ary_grep, 1);
+ rb_define_method(rb_cArray, "flat_map", rb_ary_flat_map, 0);
+ rb_define_method(rb_cArray, "collect_concat", rb_ary_flat_map, 0);
+
id_cmp = rb_intern("<=>");
id_random = rb_intern("random");
id_div = rb_intern("div");
id_power = rb_intern("**");
+ id_call = rb_intern("call");
}
diff --git a/enum.c b/enum.c
index 7920b93c5543bd..a0cfa2e590410e 100644
--- a/enum.c
+++ b/enum.c
@@ -15,8 +15,6 @@
#include "id.h"
#include "internal.h"
-VALUE rb_f_send(int argc, VALUE *argv, VALUE recv);
-
VALUE rb_mEnumerable;
static ID id_next;
diff --git a/internal.h b/internal.h
index 1a9be71c31eaa6..ffe9f70d5f7156 100644
--- a/internal.h
+++ b/internal.h
@@ -976,6 +976,7 @@ typedef void rb_check_funcall_hook(int, VALUE, ID, int, const VALUE *, VALUE);
VALUE rb_check_funcall_with_hook(VALUE recv, ID mid, int argc, const VALUE *argv,
rb_check_funcall_hook *hook, VALUE arg);
VALUE rb_catch_protect(VALUE t, rb_block_call_func *func, VALUE data, int *stateptr);
+VALUE rb_f_send(int argc, VALUE *argv, VALUE recv);
/* vm_insnhelper.c */
VALUE rb_equal_opt(VALUE obj1, VALUE obj2);