summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorknu <knu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-12-11 10:16:59 +0000
committerknu <knu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-12-11 10:16:59 +0000
commitf4b13fabe618a5747dee135c5caf1795a73a77c5 (patch)
tree15feeadf3da16864cfadb37ca00a46ae1bdb872d
parent14df5ba882e1dd411da0beb7d3cc2fdf8e5fb7a8 (diff)
* enumerator.c (enum_each_with_object): Add
Enumerable#each_with_object and Enumerator#with_object. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@20627 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog5
-rw-r--r--NEWS8
-rw-r--r--enumerator.c74
3 files changed, 87 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index 9eb2302b46..88e9e4236b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Thu Dec 11 19:08:38 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * enumerator.c (enum_each_with_object): Add
+ Enumerable#each_with_object and Enumerator#with_object.
+
Wed Dec 10 21:35:12 2008 Kouhei Sutou <kou@cozmixng.org>
* lib/rss/maker.rb (RSS::Maker.[]): add.
diff --git a/NEWS b/NEWS
index cd721ed5c6..64623b3f4d 100644
--- a/NEWS
+++ b/NEWS
@@ -26,6 +26,14 @@ with all sufficient information, see the ChangeLog file.
New method with which replaces #choice.
+ * Enumerable#each_with_object
+
+ New method.
+
+ * Enumerator#with_object
+
+ New method.
+
* Hash#default_proc=
New method.
diff --git a/enumerator.c b/enumerator.c
index 896863a78a..71362c168c 100644
--- a/enumerator.c
+++ b/enumerator.c
@@ -208,6 +208,39 @@ enum_each_cons(obj, n)
return Qnil;
}
+static VALUE
+each_with_object_i(val, memo)
+ VALUE val, memo;
+{
+ return rb_yield_values(2, val, memo);
+}
+
+/*
+ * call-seq:
+ * each_with_object(obj) {|(*args), memo_obj| ... }
+ * each_with_object(obj)
+ *
+ * Iterates the given block for each element with an arbitrary
+ * object given, and returns the initially given object.
+
+ * If no block is given, returns an enumerator.
+ *
+ * e.g.:
+ * evens = (1..10).each_with_object([]) {|i, a| a << i*2 }
+ * # => [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
+ *
+ */
+static VALUE
+enum_each_with_object(obj, memo)
+ VALUE obj, memo;
+{
+ RETURN_ENUMERATOR(obj, 1, &memo);
+
+ rb_block_call(obj, SYM2ID(sym_each), 0, 0, each_with_object_i, memo);
+
+ return memo;
+}
+
static VALUE enumerator_allocate _((VALUE));
static VALUE
enumerator_allocate(klass)
@@ -380,6 +413,44 @@ enumerator_with_index(obj)
enumerator_with_index_i, (VALUE)&memo);
}
+static VALUE
+enumerator_with_object_i(val, memo)
+ VALUE val, memo;
+{
+ return rb_yield_values(2, val, memo);
+}
+
+/*
+ * call-seq:
+ * e.with_object(obj) {|(*args), memo_obj| ... }
+ * e.with_object(obj)
+ *
+ * Iterates the given block for each element with an arbitrary
+ * object given, and returns the initially given object.
+ *
+ * If no block is given, returns an enumerator.
+ *
+ */
+static VALUE
+enumerator_with_object(obj, memo)
+ VALUE obj, memo;
+{
+ struct enumerator *e;
+ int argc = 0;
+ VALUE *argv = 0;
+
+ RETURN_ENUMERATOR(obj, 1, &memo);
+ e = enumerator_ptr(obj);
+ if (e->args) {
+ argc = RARRAY_LEN(e->args);
+ argv = RARRAY_PTR(e->args);
+ }
+ rb_block_call(e->obj, e->meth, argc, argv,
+ enumerator_with_object_i, memo);
+
+ return memo;
+}
+
/*
* call-seq:
* e.next => object
@@ -429,6 +500,7 @@ Init_Enumerator()
rb_define_method(rb_mEnumerable, "enum_slice", enum_each_slice, 1);
rb_define_method(rb_mEnumerable, "each_cons", enum_each_cons, 1);
rb_define_method(rb_mEnumerable, "enum_cons", enum_each_cons, 1);
+ rb_define_method(rb_mEnumerable, "each_with_object", enum_each_with_object, 1);
rb_cEnumerator = rb_define_class("Enumerator", rb_cObject);
rb_include_module(rb_cEnumerator, rb_mEnumerable);
@@ -438,7 +510,9 @@ Init_Enumerator()
rb_define_method(rb_cEnumerator, "initialize_copy", enumerator_init_copy, 1);
rb_define_method(rb_cEnumerator, "each", enumerator_each, 0);
rb_define_method(rb_cEnumerator, "each_with_index", enumerator_with_index, 0);
+ rb_define_method(rb_cEnumerator, "each_with_object", enumerator_with_object, 1);
rb_define_method(rb_cEnumerator, "with_index", enumerator_with_index, 0);
+ rb_define_method(rb_cEnumerator, "with_object", enumerator_with_object, 1);
rb_define_method(rb_cEnumerator, "next", enumerator_next, 0);
rb_define_method(rb_cEnumerator, "rewind", enumerator_rewind, 0);