Skip to content

Commit 77dcdf5

Browse files
committed
* enumerator.c: add Enumerable#lazy. based on the patch by
Innokenty Mikhailov at <ruby#101> [ruby-core:37164] [Feature ruby#4890] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@34951 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
1 parent 0b327a6 commit 77dcdf5

File tree

3 files changed

+181
-1
lines changed

3 files changed

+181
-1
lines changed

ChangeLog

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
Fri Mar 9 00:30:23 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
2+
3+
* enumerator.c: add Enumerable#lazy. based on the patch by
4+
Innokenty Mikhailov at <https://github.com/ruby/ruby/pull/101>
5+
[ruby-core:37164] [Feature #4890]
6+
17
Fri Mar 9 00:25:59 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
28

39
* enumerator.c (enumerator_each, generator_each): pass arguments to

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ with all sufficient information, see the ChangeLog file.
1717

1818
* builtin classes
1919

20+
* Enumerable
21+
* added method:
22+
* added Enumerable#lazy method for lazy enumeration.
23+
2024
* Kernel
2125
* added method:
2226
* added Kernel#Hash conversion method like Array() or Float().

enumerator.c

Lines changed: 171 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,8 @@
102102
*
103103
*/
104104
VALUE rb_cEnumerator;
105-
static ID id_rewind, id_each;
105+
VALUE rb_cLazy;
106+
static ID id_rewind, id_each, id_new, id_initialize, id_yield, id_call;
106107
static VALUE sym_each;
107108

108109
VALUE rb_eStopIteration;
@@ -1200,6 +1201,159 @@ generator_each(int argc, VALUE *argv, VALUE obj)
12001201
* end
12011202
*
12021203
*/
1204+
1205+
/* Lazy Enumerator methods */
1206+
static VALUE
1207+
lazy_init_iterator(VALUE val, VALUE m, int argc, VALUE *argv)
1208+
{
1209+
VALUE args[2];
1210+
args[0] = m;
1211+
args[1] = val;
1212+
return rb_yield_values2(2, args);
1213+
}
1214+
1215+
static VALUE
1216+
lazy_init_yielder(VALUE val, VALUE m, int argc, VALUE *argv)
1217+
{
1218+
return rb_funcall2(m, id_yield, 1, &val);
1219+
}
1220+
1221+
static VALUE
1222+
lazy_init_block_i(VALUE val, VALUE m, int argc, VALUE *argv)
1223+
{
1224+
return rb_block_call(m, id_each, argc-1, argv+1, lazy_init_iterator, val);
1225+
}
1226+
1227+
static VALUE
1228+
lazy_init_block(VALUE val, VALUE m, int argc, VALUE *argv)
1229+
{
1230+
return rb_block_call(m, id_each, argc-1, argv+1, lazy_init_yielder, val);
1231+
}
1232+
1233+
static VALUE
1234+
lazy_initialize(int argc, VALUE *argv, VALUE obj)
1235+
{
1236+
VALUE generator, arg;
1237+
1238+
if (argc < 1) rb_raise(rb_eArgError, "wrong number of arguments(%d for 1+)", argc);
1239+
--argc;
1240+
arg = *argv++;
1241+
generator = generator_allocate(rb_cGenerator);
1242+
rb_block_call(generator, id_initialize, 0, 0,
1243+
(rb_block_given_p() ? lazy_init_block_i: lazy_init_block),
1244+
arg);
1245+
enumerator_init(obj, generator, sym_each, argc, argv);
1246+
1247+
return obj;
1248+
}
1249+
1250+
/*
1251+
* call-seq:
1252+
* e.lazy -> lazy_enumerator
1253+
*/
1254+
static VALUE
1255+
enumerable_lazy(int argc, VALUE *argv, VALUE obj)
1256+
{
1257+
if (argc > 0) {
1258+
VALUE ret, buff, *args = ALLOCV_N(VALUE, buff, argc + 1);
1259+
args[0] = obj;
1260+
MEMCPY(args + 1, argv, VALUE, argc);
1261+
ret = rb_class_new_instance(argc + 1, args, rb_cLazy);
1262+
ALLOCV_END(buff);
1263+
return ret;
1264+
}
1265+
else {
1266+
return rb_class_new_instance(1, &obj, rb_cLazy);
1267+
}
1268+
}
1269+
1270+
static VALUE
1271+
lazy_map_func(VALUE val, VALUE m, int argc, VALUE *argv)
1272+
{
1273+
VALUE result = rb_yield_values2(argc - 1, &argv[1]);
1274+
1275+
return rb_funcall(argv[0], id_yield, 1, result);
1276+
}
1277+
1278+
static VALUE
1279+
lazy_map(VALUE obj)
1280+
{
1281+
if (!rb_block_given_p()) {
1282+
rb_raise(rb_eArgError, "tried to call lazy map without a block");
1283+
}
1284+
1285+
return rb_block_call(rb_cLazy, id_new, 1, &obj, lazy_map_func, 0);
1286+
}
1287+
1288+
1289+
static VALUE
1290+
lazy_select_func(VALUE val, VALUE m, int argc, VALUE *argv)
1291+
{
1292+
VALUE element = argv[1];
1293+
VALUE result = rb_yield_values2(argc - 1, &argv[1]);
1294+
1295+
if (RTEST(result)) {
1296+
return rb_funcall(argv[0], id_yield, 1, element);
1297+
}
1298+
else {
1299+
return result;
1300+
}
1301+
}
1302+
1303+
static VALUE
1304+
lazy_select(VALUE obj)
1305+
{
1306+
if (!rb_block_given_p()) {
1307+
rb_raise(rb_eArgError, "tried to call lazy select without a block");
1308+
}
1309+
1310+
return rb_block_call(rb_cLazy, id_new, 1, &obj, lazy_select_func, 0);
1311+
}
1312+
1313+
static VALUE
1314+
lazy_reject_func(VALUE val, VALUE m, int argc, VALUE *argv)
1315+
{
1316+
VALUE element = argv[1];
1317+
VALUE result = rb_yield_values2(argc - 1, &argv[1]);
1318+
1319+
if (!RTEST(result)) {
1320+
return rb_funcall(argv[0], id_yield, 1, element);
1321+
}
1322+
else {
1323+
return result;
1324+
}
1325+
}
1326+
1327+
static VALUE
1328+
lazy_reject(VALUE obj)
1329+
{
1330+
if (!rb_block_given_p()) {
1331+
rb_raise(rb_eArgError, "tried to call lazy reject without a block");
1332+
}
1333+
1334+
return rb_block_call(rb_cLazy, id_new, 1, &obj, lazy_reject_func, 0);
1335+
}
1336+
1337+
static VALUE
1338+
lazy_grep_func(VALUE val, VALUE m, int argc, VALUE *argv)
1339+
{
1340+
VALUE element = argv[1];
1341+
VALUE result = rb_funcall(m, rb_intern("=~"), 1, element);
1342+
1343+
if (RTEST(result)) {
1344+
return rb_funcall(argv[0], id_yield, 1, element);
1345+
}
1346+
else {
1347+
return result;
1348+
}
1349+
}
1350+
1351+
static VALUE
1352+
lazy_grep(VALUE obj, VALUE pattern)
1353+
{
1354+
return rb_block_call(rb_cLazy, id_new, 1, &obj, lazy_grep_func, pattern);
1355+
}
1356+
12031357
static VALUE
12041358
stop_result(VALUE self)
12051359
{
@@ -1231,6 +1385,18 @@ Init_Enumerator(void)
12311385
rb_define_method(rb_cEnumerator, "rewind", enumerator_rewind, 0);
12321386
rb_define_method(rb_cEnumerator, "inspect", enumerator_inspect, 0);
12331387

1388+
/* Enumerable::Lazy */
1389+
rb_cLazy = rb_define_class_under(rb_mEnumerable, "Lazy", rb_cEnumerator);
1390+
rb_define_method(rb_mEnumerable, "lazy", enumerable_lazy, -1);
1391+
rb_define_method(rb_cLazy, "initialize", lazy_initialize, -1);
1392+
rb_define_method(rb_cLazy, "map", lazy_map, 0);
1393+
rb_define_method(rb_cLazy, "select", lazy_select, 0);
1394+
rb_define_method(rb_cLazy, "reject", lazy_reject, 0);
1395+
rb_define_method(rb_cLazy, "grep", lazy_grep, 1);
1396+
1397+
rb_define_alias(rb_cLazy, "collect", "map");
1398+
rb_define_alias(rb_cLazy, "find_all", "select");
1399+
12341400
rb_eStopIteration = rb_define_class("StopIteration", rb_eIndexError);
12351401
rb_define_method(rb_eStopIteration, "result", stop_result, 0);
12361402

@@ -1251,6 +1417,10 @@ Init_Enumerator(void)
12511417

12521418
id_rewind = rb_intern("rewind");
12531419
id_each = rb_intern("each");
1420+
id_call = rb_intern("call");
1421+
id_yield = rb_intern("yield");
1422+
id_new = rb_intern("new");
1423+
id_initialize = rb_intern("initialize");
12541424
sym_each = ID2SYM(id_each);
12551425

12561426
rb_provide("enumerator.so"); /* for backward compatibility */

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy