6
$Date: 2007-06-01 01:59:12 +0900 (金, 01 6月 2007) $
6
$Date: 2007-08-25 12:29:39 +0900 (土, 25 8月 2007) $
7
7
created at: Fri Oct 1 15:15:19 JST 1993
9
Copyright (C) 1993-2003 Yukihiro Matsumoto
9
Copyright (C) 1993-2007 Yukihiro Matsumoto
11
11
**********************************************************************/
13
#include "ruby/ruby.h"
14
#include "ruby/node.h"
15
#include "ruby/util.h"
17
17
VALUE rb_mEnumerable;
18
static ID id_each, id_eqq, id_cmp;
18
static ID id_each, id_eqq, id_cmp, id_next;
21
21
grep_i(VALUE i, VALUE *arg)
628
628
VALUE a = (*(NODE *const *)ap)->u1.value;
629
629
VALUE b = (*(NODE *const *)bp)->u1.value;
630
VALUE ary = (VALUE)data;
632
if (RBASIC(ary)->klass) {
633
rb_raise(rb_eRuntimeError, "sort_by reentered");
631
635
return rb_cmpint(rb_funcall(a, id_cmp, 1, b), a, b);
717
721
RBASIC(ary)->klass = 0;
718
722
rb_block_call(obj, id_each, 0, 0, sort_by_i, ary);
719
723
if (RARRAY_LEN(ary) > 1) {
720
ruby_qsort(RARRAY_PTR(ary), RARRAY_LEN(ary), sizeof(VALUE), sort_by_cmp, 0);
724
ruby_qsort(RARRAY_PTR(ary), RARRAY_LEN(ary), sizeof(VALUE),
725
sort_by_cmp, (void *)ary);
722
727
if (RBASIC(ary)->klass) {
723
728
rb_raise(rb_eRuntimeError, "sort_by reentered");
1056
minmax_i(VALUE i, VALUE *memo)
1060
if (memo[0] == Qundef) {
1065
n = rb_cmpint(rb_funcall(i, id_cmp, 1, memo[0]), i, memo[0]);
1069
n = rb_cmpint(rb_funcall(i, id_cmp, 1, memo[1]), i, memo[1]);
1078
minmax_ii(VALUE i, VALUE *memo)
1082
if (memo[0] == Qundef) {
1087
VALUE ary = memo[2];
1089
RARRAY_PTR(ary)[0] = i;
1090
RARRAY_PTR(ary)[1] = memo[0];
1091
n = rb_cmpint(rb_yield(ary), i, memo[0]);
1095
RARRAY_PTR(ary)[0] = i;
1096
RARRAY_PTR(ary)[1] = memo[1];
1097
n = rb_cmpint(rb_yield(ary), i, memo[1]);
1107
* enum.minmax => [min,max]
1108
* enum.minmax {|a,b| block } => [min,max]
1110
* Returns two elements array which contains the mininum and the
1111
* maxinum value in the enumerable. The first form assumes all
1112
* objects implement <code>Comparable</code>; the second uses the
1113
* block to return <em>a <=> b</em>.
1115
* a = %w(albatross dog horse)
1116
* a.minmax #=> ["albatross", "horse"]
1117
* a.minmax {|a,b| a.length <=> b.length } #=> ["dog", "albatross"]
1121
enum_minmax(VALUE obj)
1124
VALUE ary = rb_ary_new3(2, Qnil, Qnil);
1127
if (rb_block_given_p()) {
1129
rb_block_call(obj, id_each, 0, 0, minmax_ii, (VALUE)result);
1132
rb_block_call(obj, id_each, 0, 0, minmax_i, (VALUE)result);
1134
if (result[0] != Qundef) {
1135
RARRAY_PTR(ary)[0] = result[0];
1136
RARRAY_PTR(ary)[1] = result[1];
1051
1142
min_by_i(VALUE i, VALUE *memo)
1224
minmax_by_i(VALUE i, VALUE *memo)
1229
if (memo[0] == Qundef) {
1236
if (rb_cmpint(rb_funcall(v, id_cmp, 1, memo[0]), v, memo[0]) < 0) {
1240
if (rb_cmpint(rb_funcall(v, id_cmp, 1, memo[1]), v, memo[1]) > 0) {
1250
* enum.minmax_by {| obj| block } => [min, max]
1252
* Returns two elements array array containing the objects in
1253
* <i>enum</i> that gives the minmum and maximum values respectively
1254
* from the given block.
1256
* a = %w(albatross dog horse)
1257
* a.minmax_by {|x| x.length } #=> ["dog", "albatross"]
1261
enum_minmax_by(VALUE obj)
1265
RETURN_ENUMERATOR(obj, 0, 0);
1271
rb_block_call(obj, id_each, 0, 0, minmax_by_i, (VALUE)memo);
1272
return rb_assoc_new(memo[2], memo[3]);
1133
1276
member_i(VALUE item, VALUE *memo)
1135
1278
if (rb_equal(item, memo[0])) {
1208
zip_i(VALUE val, VALUE *memo)
1351
zip_i(VALUE val, NODE *memo)
1210
VALUE result = memo[0];
1211
VALUE args = memo[1];
1212
int idx = memo[2]++;
1353
volatile VALUE result = memo->u1.value;
1354
volatile VALUE args = memo->u2.value;
1216
1358
tmp = rb_ary_new2(RARRAY_LEN(args) + 1);
1217
1359
rb_ary_store(tmp, 0, val);
1218
1360
for (i=0; i<RARRAY_LEN(args); i++) {
1219
rb_ary_push(tmp, rb_ary_entry(RARRAY_PTR(args)[i], idx));
1361
VALUE v = rb_funcall(RARRAY_PTR(args)[i], id_next, 0, 0);
1362
rb_ary_push(tmp, v);
1221
if (rb_block_given_p()) {
1364
if (NIL_P(result)) {
1376
return rb_block_call(memo->u3.value, id_each, 0, 0, zip_i, (VALUE)memo);
1232
* enum.zip(arg, ...) => array
1381
* enum.zip(arg, ...) => enumerator
1233
1382
* enum.zip(arg, ...) {|arr| block } => nil
1235
* Converts any arguments to arrays, then merges elements of
1236
* <i>enum</i> with corresponding elements from each argument. This
1237
* generates a sequence of <code>enum#size</code> <em>n</em>-element
1238
* arrays, where <em>n</em> is one more that the count of arguments. If
1239
* the size of any argument is less than <code>enum#size</code>,
1240
* <code>nil</code> values are supplied. If a block given, it is
1241
* invoked for each output array, otherwise an array of arrays is
1384
* Takes one element from <i>enum</i> and merges corresponding
1385
* elements from each <i>args</i>. This generates a sequence of
1386
* <em>n</em>-element arrays, where <em>n</em> is one more that the
1387
* count of arguments. The length of the sequence is truncated to
1388
* the size of the shortest argument (or <i>enum</i>). If a block
1389
* given, it is invoked for each output array, otherwise an array of
1390
* arrays is returned.
1244
1392
* a = [ 4, 5, 6 ]
1245
1393
* b = [ 7, 8, 9 ]
1247
* (1..3).zip(a, b) #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
1248
* "cat\ndog".zip([1]) #=> [["cat\n", 1], ["dog", nil]]
1249
* (1..3).zip #=> [[1], [2], [3]]
1395
* [1,2,3].zip(a, b) #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
1396
* [1,2].zip(a,b) #=> [[1, 4, 7], [2, 5, 8]]
1397
* a.zip([1,2],[8]) #=> [[4,1,8]]
1260
1408
for (i=0; i<argc; i++) {
1261
argv[i] = rb_convert_type(argv[i], T_ARRAY, "Array", "to_a");
1409
argv[i] = rb_funcall(argv[i], rb_intern("to_enum"), 1, ID2SYM(id_each));
1263
1411
RETURN_ENUMERATOR(obj, argc, argv);
1264
1412
result = rb_block_given_p() ? Qnil : rb_ary_new();
1266
memo[1] = rb_ary_new4(argc, argv);
1268
rb_block_call(obj, id_each, 0, 0, zip_i, (VALUE)memo);
1413
memo = rb_node_newnode(NODE_MEMO, result, rb_ary_new4(argc, argv), obj);
1414
rb_rescue2(zip_b, (VALUE)memo, 0, 0, rb_eStopIteration, (VALUE)0);
1383
1529
return args[0];
1534
cycle_i(VALUE i, VALUE ary)
1536
rb_ary_push(ary, i);
1543
* enum.cycle {|obj| block }
1545
* Calls <i>block</i> for each element of enumerable repeatedly
1546
* forever. Enumerable#cycle saves elements in an internal array.
1548
* a = ["a", "b", "c"]
1549
* a.cycle {|x| puts x } # print, a, b, c, a, b, c,.. forever.
1554
enum_cycle(VALUE obj)
1559
RETURN_ENUMERATOR(obj, 0, 0);
1561
rb_block_call(obj, id_each, 0, 0, cycle_i, ary);
1563
for (i=0; i<RARRAY_LEN(ary); i++) {
1564
rb_yield(RARRAY_PTR(ary)[i]);
1387
1571
* The <code>Enumerable</code> mixin provides collection classes with
1388
1572
* several traversal and searching methods, and with the ability to
1425
1609
rb_define_method(rb_mEnumerable,"none?", enum_none, 0);
1426
1610
rb_define_method(rb_mEnumerable,"min", enum_min, 0);
1427
1611
rb_define_method(rb_mEnumerable,"max", enum_max, 0);
1428
rb_define_method(rb_mEnumerable,"min_by", enum_min_by, 0);
1429
rb_define_method(rb_mEnumerable,"max_by", enum_max_by, 0);
1612
rb_define_method(rb_mEnumerable,"minmax", enum_minmax, 0);
1613
rb_define_method(rb_mEnumerable,"min_by", enum_min_by, 0);
1614
rb_define_method(rb_mEnumerable,"max_by", enum_max_by, 0);
1615
rb_define_method(rb_mEnumerable,"minmax_by", enum_minmax_by, 0);
1430
1616
rb_define_method(rb_mEnumerable,"member?", enum_member, 1);
1431
1617
rb_define_method(rb_mEnumerable,"include?", enum_member, 1);
1432
1618
rb_define_method(rb_mEnumerable,"each_with_index", enum_each_with_index, -1);
1433
1619
rb_define_method(rb_mEnumerable, "zip", enum_zip, -1);
1434
1620
rb_define_method(rb_mEnumerable, "take", enum_take, -1);
1435
1621
rb_define_method(rb_mEnumerable, "drop", enum_drop, -1);
1622
rb_define_method(rb_mEnumerable, "cycle", enum_cycle, 0);
1437
1624
id_eqq = rb_intern("===");
1438
1625
id_each = rb_intern("each");
1439
1626
id_cmp = rb_intern("<=>");
1627
id_next = rb_intern("next");