summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2005-07-14 15:15:22 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2005-07-14 15:15:22 +0000
commitd725e6666a76ec9d0f5fda7fc24262cb4b498c17 (patch)
treea1393f9e88e66ae7e9a4a7f7b41ef4a1b9670659
parentf1fbedf1a622710984dd9836947214f4ce169772 (diff)
* enum.c (enumeratorize): create new enumerator for current method if
no block is given. * enumerator.c: moved from ext/enumerator. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8764 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog7
-rw-r--r--common.mk2
-rw-r--r--enum.c43
-rw-r--r--enumerator.c (renamed from ext/enumerator/enumerator.c)199
-rw-r--r--ext/enumerator/.cvsignore2
-rw-r--r--ext/enumerator/enumerator.txt102
-rw-r--r--ext/enumerator/extconf.rb2
-rw-r--r--inits.c2
-rw-r--r--intern.h2
9 files changed, 212 insertions, 149 deletions
diff --git a/ChangeLog b/ChangeLog
index e495880bc2..44a88ed10c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Thu Jul 15 00:11:36 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * enum.c (enumeratorize): create new enumerator for current method if
+ no block is given.
+
+ * enumerator.c: moved from ext/enumerator.
+
Thu Jul 14 18:27:35 2005 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
* win32/win32.c (rb_w32_strerror): should return correct message
diff --git a/common.mk b/common.mk
index f9cab19e2a..a44396dc65 100644
--- a/common.mk
+++ b/common.mk
@@ -224,6 +224,8 @@ dmyext.$(OBJEXT): {$(VPATH)}dmyext.c
enum.$(OBJEXT): {$(VPATH)}enum.c {$(VPATH)}ruby.h config.h \
{$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
{$(VPATH)}node.h {$(VPATH)}util.h
+enumerator.$(OBJEXT): {$(VPATH)}enumerator.c {$(VPATH)}ruby.h config.h \
+ {$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h
error.$(OBJEXT): {$(VPATH)}error.c {$(VPATH)}ruby.h config.h \
{$(VPATH)}defines.h {$(VPATH)}intern.h {$(VPATH)}missing.h \
{$(VPATH)}env.h {$(VPATH)}st.h
diff --git a/enum.c b/enum.c
index 3f9ae1d00a..2b572c85ba 100644
--- a/enum.c
+++ b/enum.c
@@ -17,6 +17,15 @@
VALUE rb_mEnumerable;
static ID id_each, id_eqq, id_cmp;
+static VALUE
+enumeratorize(argc, argv, obj)
+ int argc;
+ VALUE *argv;
+ VALUE obj;
+{
+ return rb_enumeratorize(obj, ID2SYM(rb_frame_this_func()), argc, argv);
+}
+
VALUE
rb_each(obj)
VALUE obj;
@@ -114,6 +123,8 @@ enum_find(argc, argv, obj)
VALUE if_none;
rb_scan_args(argc, argv, "01", &if_none);
+ if (!rb_block_given_p())
+ return enumeratorize(argc, argv, obj);
rb_iterate(rb_each, obj, find_i, (VALUE)&memo);
if (memo != Qundef) {
return memo;
@@ -151,8 +162,11 @@ static VALUE
enum_find_all(obj)
VALUE obj;
{
- VALUE ary = rb_ary_new();
+ VALUE ary;
+ if (!rb_block_given_p()) return enumeratorize(0, 0, obj);
+
+ ary = rb_ary_new();
rb_iterate(rb_each, obj, find_all_i, ary);
return ary;
@@ -183,8 +197,11 @@ static VALUE
enum_reject(obj)
VALUE obj;
{
- VALUE ary = rb_ary_new();
+ VALUE ary;
+ if (!rb_block_given_p()) return enumeratorize(0, 0, obj);
+
+ ary = rb_ary_new();
rb_iterate(rb_each, obj, reject_i, ary);
return ary;
@@ -225,9 +242,12 @@ static VALUE
enum_collect(obj)
VALUE obj;
{
- VALUE ary = rb_ary_new();
+ VALUE ary;
+
+ if (!rb_block_given_p()) return enumeratorize(0, 0, obj);
- rb_iterate(rb_each, obj, rb_block_given_p() ? collect_i : collect_all, ary);
+ ary = rb_ary_new();
+ rb_iterate(rb_each, obj, collect_i, ary);
return ary;
}
@@ -343,6 +363,8 @@ enum_partition(obj)
{
VALUE ary[2];
+ if (!rb_block_given_p()) return enumeratorize(0, 0, obj);
+
ary[0] = rb_ary_new();
ary[1] = rb_ary_new();
rb_iterate(rb_each, obj, partition_i, (VALUE)ary);
@@ -476,6 +498,8 @@ enum_sort_by(obj)
VALUE ary;
long i;
+ if (!rb_block_given_p()) return enumeratorize(0, 0, obj);
+
if (TYPE(obj) == T_ARRAY) {
ary = rb_ary_new2(RARRAY(obj)->len);
}
@@ -763,7 +787,8 @@ enum_min_by(obj)
{
VALUE memo[2];
- rb_need_block();
+ if (!rb_block_given_p()) return enumeratorize(0, 0, obj);
+
memo[0] = Qundef;
memo[1] = Qnil;
rb_iterate(rb_each, obj, min_by_i, (VALUE)memo);
@@ -806,7 +831,8 @@ enum_max_by(obj)
{
VALUE memo[2];
- rb_need_block();
+ if (!rb_block_given_p()) return enumeratorize(0, 0, obj);
+
memo[0] = Qundef;
memo[1] = Qnil;
rb_iterate(rb_each, obj, max_by_i, (VALUE)memo);
@@ -844,6 +870,8 @@ enum_member(obj, val)
{
VALUE memo[2];
+ if (!rb_block_given_p()) return enumeratorize(1, &val, obj);
+
memo[0] = val;
memo[1] = Qfalse;
rb_iterate(rb_each, obj, member_i, (VALUE)memo);
@@ -881,7 +909,8 @@ enum_each_with_index(obj)
{
VALUE memo = 0;
- rb_need_block();
+ if (!rb_block_given_p()) return enumeratorize(0, 0, obj);
+
rb_iterate(rb_each, obj, each_with_index_i, (VALUE)&memo);
return obj;
}
diff --git a/ext/enumerator/enumerator.c b/enumerator.c
index 5668019753..46854695a3 100644
--- a/ext/enumerator/enumerator.c
+++ b/enumerator.c
@@ -13,10 +13,15 @@
************************************************/
#include "ruby.h"
-#include "node.h"
+/*
+ * Document-class: Enumerable::Enumerator
+ *
+ * A class which provides a method `each' to be used as an Enumerable
+ * object.
+ */
static VALUE rb_cEnumerator;
-static ID sym_each, sym_each_with_index, sym_each_slice, sym_each_cons;
+static VALUE sym_each, sym_each_with_index, sym_each_slice, sym_each_cons;
static VALUE
proc_call(proc, args)
@@ -86,25 +91,51 @@ enumerator_iter_i(i, e)
return rb_yield(proc_call(e->proc, i));
}
+/*
+ * call-seq:
+ * obj.to_enum(method = :each, *args)
+ * obj.enum_for(method = :each, *args)
+ *
+ * Returns Enumerable::Enumerator.new(self, method, *args).
+ *
+ * e.g.:
+ * str = "xyz"
+ *
+ * enum = str.enum_for(:each_byte)
+ * a = enum.map {|b| '%02x' % b } #=> ["78", "79", "7a"]
+ *
+ * # protects an array from being modified
+ * a = [1, 2, 3]
+ * some_method(a.to_enum)
+ *
+ */
static VALUE
-obj_to_enum(obj, enum_args)
- VALUE obj, enum_args;
+obj_to_enum(argc, argv, obj)
+ int argc;
+ VALUE *argv;
+ VALUE obj;
{
- rb_ary_unshift(enum_args, obj);
+ VALUE meth = sym_each;
- return rb_class_new_instance(RARRAY(enum_args)->len,
- RARRAY(enum_args)->ptr,
- rb_cEnumerator);
+ if (argc > 0) {
+ --argc;
+ meth = *argv++;
+ }
+ return rb_enumeratorize(obj, meth, argc, argv);
}
+/*
+ * call-seq:
+ * enum_with_index
+ *
+ * Returns Enumerable::Enumerator.new(self, :each_with_index).
+ *
+ */
static VALUE
enumerator_enum_with_index(obj)
VALUE obj;
{
- VALUE args[2];
- args[0] = obj;
- args[1] = sym_each_with_index;
- return rb_class_new_instance(2, args, rb_cEnumerator);
+ return rb_enumeratorize(obj, sym_each_with_index, 0, 0);
}
static VALUE
@@ -125,6 +156,21 @@ each_slice_i(val, memo)
return Qnil;
}
+/*
+ * call-seq:
+ * e.each_slice(n) {...}
+ *
+ * Iterates the given block for each slice of <n> elements.
+ *
+ * e.g.:
+ * (1..10).each_slice(3) {|a| p a}
+ * # outputs below
+ * [1, 2, 3]
+ * [4, 5, 6]
+ * [7, 8, 9]
+ * [10]
+ *
+ */
static VALUE
enum_each_slice(obj, n)
VALUE obj, n;
@@ -145,15 +191,18 @@ enum_each_slice(obj, n)
return Qnil;
}
+/*
+ * call-seq:
+ * e.enum_slice(n)
+ *
+ * Returns Enumerable::Enumerator.new(self, :each_slice, n).
+ *
+ */
static VALUE
enumerator_enum_slice(obj, n)
VALUE obj, n;
{
- VALUE args[2];
- args[0] = obj;
- args[1] = sym_each_slice;
- args[2] = n;
- return rb_class_new_instance(3, args, rb_cEnumerator);
+ return rb_enumeratorize(obj, sym_each_slice, 1, &n);
}
static VALUE
@@ -174,6 +223,26 @@ each_cons_i(val, memo)
return Qnil;
}
+/*
+ * call-seq:
+ * each_cons(n) {...}
+ *
+ * Iterates the given block for each array of consecutive <n>
+ * elements.
+ *
+ * e.g.:
+ * (1..10).each_cons(3) {|a| p a}
+ * # outputs below
+ * [1, 2, 3]
+ * [2, 3, 4]
+ * [3, 4, 5]
+ * [4, 5, 6]
+ * [5, 6, 7]
+ * [6, 7, 8]
+ * [7, 8, 9]
+ * [8, 9, 10]
+ *
+ */
static VALUE
enum_each_cons(obj, n)
VALUE obj, n;
@@ -190,15 +259,18 @@ enum_each_cons(obj, n)
return Qnil;
}
+/*
+ * call-seq:
+ * e.enum_cons(n)
+ *
+ * Returns Enumerable::Enumerator.new(self, :each_cons, n).
+ *
+ */
static VALUE
enumerator_enum_cons(obj, n)
VALUE obj, n;
{
- VALUE args[2];
- args[0] = obj;
- args[1] = sym_each_cons;
- args[2] = n;
- return rb_class_new_instance(3, args, rb_cEnumerator);
+ return rb_enumeratorize(obj, sym_each_cons, 1, &n);
}
static VALUE enumerator_allocate _((VALUE));
@@ -211,21 +283,15 @@ enumerator_allocate(klass)
enumerator_mark, -1, ptr);
}
-static VALUE
-enumerator_initialize(argc, argv, obj)
+VALUE
+enumerator_init(enum_obj, obj, meth, argc, argv)
+ VALUE enum_obj, obj, meth;
int argc;
VALUE *argv;
- VALUE obj;
{
- VALUE enum_obj, enum_method, enum_args;
- struct enumerator *ptr = enumerator_ptr(obj);
-
- rb_scan_args(argc, argv, "11*", &enum_obj, &enum_method, &enum_args);
+ struct enumerator *ptr = enumerator_ptr(enum_obj);
- if (enum_method == Qnil)
- enum_method = sym_each;
-
- ptr->method = rb_obj_method(enum_obj, enum_method);
+ ptr->method = rb_obj_method(obj, meth);
if (rb_block_given_p()) {
ptr->proc = rb_block_proc();
ptr->iter = enumerator_iter_i;
@@ -233,9 +299,52 @@ enumerator_initialize(argc, argv, obj)
else {
ptr->iter = (VALUE (*) _((VALUE, struct enumerator *)))rb_yield;
}
- ptr->args = enum_args;
+ if (argc) ptr->args = rb_ary_new4(argc, argv);
- return obj;
+ return enum_obj;
+}
+
+/*
+ * call-seq:
+ * Enumerable::Enumerator.new(obj, method = :each, *args)
+ *
+ * Creates a new Enumerable::Enumerator object, which is to be
+ * used as an Enumerable object using the given object's given
+ * method with the given arguments.
+ *
+ * e.g.:
+ * str = "xyz"
+ *
+ * enum = Enumerable::Enumerator.new(str, :each_byte)
+ * a = enum.map {|b| '%02x' % b } #=> ["78", "79", "7a"]
+ *
+ */
+static VALUE
+enumerator_initialize(argc, argv, obj)
+ int argc;
+ VALUE *argv;
+ VALUE obj;
+{
+ struct enumerator *ptr = enumerator_ptr(obj);
+ VALUE recv, meth = sym_each;
+
+ if (argc == 0)
+ rb_raise(rb_eArgError, "wrong number of argument (0 for 1)");
+ recv = *argv++;
+ if (--argc) {
+ meth = *argv++;
+ --argc;
+ }
+ return enumerator_init(obj, recv, meth, argc, argv);
+}
+
+VALUE
+rb_enumeratorize(obj, meth, argc, argv)
+ VALUE obj, meth;
+ int argc;
+ VALUE *argv;
+{
+ return enumerator_init(enumerator_allocate(rb_cEnumerator), obj, meth, argc, argv);
}
static VALUE enumerator_iter _((VALUE));
@@ -248,6 +357,14 @@ enumerator_iter(memo)
return method_call(e->method, e->args);
}
+/*
+ * call-seq:
+ * enum.each {...}
+ *
+ * Iterates the given block using the object and the method specified
+ * in the first place.
+ *
+ */
static VALUE
enumerator_each(obj)
VALUE obj;
@@ -266,6 +383,14 @@ enumerator_with_index_i(val, memo)
return val;
}
+/*
+ * call-seq:
+ * e.with_index {|(*args), idx| ... }
+ *
+ * Iterates the given block for each elements with an index, which
+ * start from 0.
+ *
+ */
static VALUE
enumerator_with_index(obj)
VALUE obj;
@@ -278,7 +403,7 @@ enumerator_with_index(obj)
}
void
-Init_enumerator()
+Init_Enumerator()
{
VALUE rb_mEnumerable;
@@ -305,4 +430,6 @@ Init_enumerator()
sym_each_with_index = ID2SYM(rb_intern("each_with_index"));
sym_each_slice = ID2SYM(rb_intern("each_slice"));
sym_each_cons = ID2SYM(rb_intern("each_cons"));
+
+ rb_provide("enumerator"); /* for backward compatibility */
}
diff --git a/ext/enumerator/.cvsignore b/ext/enumerator/.cvsignore
deleted file mode 100644
index fc802ff1c2..0000000000
--- a/ext/enumerator/.cvsignore
+++ /dev/null
@@ -1,2 +0,0 @@
-Makefile
-mkmf.log
diff --git a/ext/enumerator/enumerator.txt b/ext/enumerator/enumerator.txt
deleted file mode 100644
index 64c7d50226..0000000000
--- a/ext/enumerator/enumerator.txt
+++ /dev/null
@@ -1,102 +0,0 @@
-.\" enumerator.txt - -*- Indented-Text -*-
-$Idaemons: /home/cvs/rb/enumerator/enumerator.txt,v 1.2 2001/07/15 10:19:24 knu Exp $
-$RoughId: enumerator.txt,v 1.5 2003/02/20 12:24:51 knu Exp $
-$Id$
-
-** Enumerable::Enumerator(Class)
-
-A class which provides a method `each' to be used as an Enumerable
-object.
-
-Superclass: Object
-
-Mix-ins: Enumerable
-
-require 'enumerator'
-
-Class Methods:
-
- new(obj, method = :each, *args)
-
- Creates a new Enumerable::Enumerator object, which is to be
- used as an Enumerable object using the given object's given
- method with the given arguments.
-
- e.g.:
- str = "xyz"
-
- enum = Enumerable::Enumerator.new(str, :each_byte)
- a = enum.map {|b| '%02x' % b } #=> ["78", "79", "7a"]
-
-Methods:
-
- each {...}
-
- Iterates the given block using the object and the method
- specified in the first place.
-
-
-Requiring this module also adds some methods to the Object class:
-
- to_enum(method = :each, *args)
- enum_for(method = :each, *args)
-
- Returns Enumerable::Enumerator.new(self, method, *args).
-
- e.g.:
- str = "xyz"
-
- enum = str.enum_for(:each_byte)
- a = enum.map {|b| '%02x' % b } #=> ["78", "79", "7a"]
-
- # protects an array from being modified
- a = [1, 2, 3]
- some_method(a.to_enum)
-
-And the Enumerable module.
-
- each_slice(n) {...}
-
- Iterates the given block for each slice of <n> elements.
-
- e.g.:
- (1..10).each_slice(3) {|a| p a}
- # outputs below
- [1, 2, 3]
- [4, 5, 6]
- [7, 8, 9]
- [10]
-
- enum_slice(n)
-
- Returns Enumerable::Enumerator.new(self, :each_slice, n).
-
- each_cons(n) {...}
-
- Iterates the given block for each array of consecutive <n>
- elements.
-
- e.g.:
- (1..10).each_cons(3) {|a| p a}
- # outputs below
- [1, 2, 3]
- [2, 3, 4]
- [3, 4, 5]
- [4, 5, 6]
- [5, 6, 7]
- [6, 7, 8]
- [7, 8, 9]
- [8, 9, 10]
-
- enum_cons(n)
-
- Returns Enumerable::Enumerator.new(self, :each_cons, n).
-
- enum_with_index
-
- Returns Enumerable::Enumerator.new(self, :each_with_index).
-
--------------------------------------------------------
-Local variables:
-fill-column: 70
-end:
diff --git a/ext/enumerator/extconf.rb b/ext/enumerator/extconf.rb
deleted file mode 100644
index 94e2ee38b2..0000000000
--- a/ext/enumerator/extconf.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-require 'mkmf'
-create_makefile('enumerator')
diff --git a/inits.c b/inits.c
index 052573a443..cc6ea53c69 100644
--- a/inits.c
+++ b/inits.c
@@ -18,6 +18,7 @@ void Init_Binding _((void));
void Init_Comparable _((void));
void Init_Dir _((void));
void Init_Enumerable _((void));
+void Init_Enumerator _((void));
void Init_Exception _((void));
void Init_syserr _((void));
void Init_eval _((void));
@@ -80,5 +81,6 @@ rb_call_inits()
Init_Math();
Init_GC();
Init_marshal();
+ Init_Enumerator();
Init_version();
}
diff --git a/intern.h b/intern.h
index 8db36a2dae..e61e394b60 100644
--- a/intern.h
+++ b/intern.h
@@ -131,6 +131,8 @@ VALUE rb_singleton_class _((VALUE));
int rb_cmpint _((VALUE, VALUE, VALUE));
NORETURN(void rb_cmperr _((VALUE, VALUE)));
/* enum.c */
+/* enumerator.c */
+VALUE rb_enumeratorize _((VALUE, VALUE, int, VALUE *));
/* error.c */
RUBY_EXTERN int ruby_nerrs;
VALUE rb_exc_new _((VALUE, const char*, long));