* 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
This commit is contained in:
nobu 2005-07-14 15:15:22 +00:00
Родитель f1fbedf1a6
Коммит d725e6666a
9 изменённых файлов: 212 добавлений и 149 удалений

Просмотреть файл

@ -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

Просмотреть файл

@ -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

43
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;
rb_iterate(rb_each, obj, rb_block_given_p() ? collect_i : collect_all, ary);
if (!rb_block_given_p()) return enumeratorize(0, 0, obj);
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;
}

Просмотреть файл

@ -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);
struct enumerator *ptr = enumerator_ptr(enum_obj);
rb_scan_args(argc, argv, "11*", &enum_obj, &enum_method, &enum_args);
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 */
}

Просмотреть файл

@ -1,2 +0,0 @@
Makefile
mkmf.log

Просмотреть файл

@ -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:

Просмотреть файл

@ -1,2 +0,0 @@
require 'mkmf'
create_makefile('enumerator')

Просмотреть файл

@ -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();
}

Просмотреть файл

@ -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));