Ruby 2.1.5p273(2014-11-13revision48405)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

enum.c
Go to the documentation of this file.
1 /**********************************************************************
2
3 enum.c -
4
5 $Author: nagachika $
6 created at: Fri Oct 1 15:15:19 JST 1993
7
8 Copyright (C) 1993-2007 Yukihiro Matsumoto
9
10 **********************************************************************/
11
12 #include "ruby/ruby.h"
13 #include "ruby/util.h"
14 #include "node.h"
15 #include "id.h"
16 #include "internal.h"
17
18 VALUE rb_f_send(int argc, VALUE *argv, VALUE recv);
19
20 VALUE rb_mEnumerable;
21
22 static ID id_next;
23 static ID id_div;
24 static ID id_call;
25 static ID id_size;
26
27 #define id_each idEach
28 #define id_eqq idEqq
29 #define id_cmp idCmp
30 #define id_lshift idLTLT
31
32 VALUE
33 rb_enum_values_pack(int argc, const VALUE *argv)
34 {
35 if (argc == 0) return Qnil;
36 if (argc == 1) return argv[0];
37 return rb_ary_new4(argc, argv);
38 }
39
40 #define ENUM_WANT_SVALUE() do { \
41 i = rb_enum_values_pack(argc, argv); \
42 } while (0)
43
44 #define enum_yield rb_yield_values2
45
46 static VALUE
47 grep_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
48 {
49 NODE *memo = RNODE(args);
50 ENUM_WANT_SVALUE();
51
52 if (RTEST(rb_funcall(memo->u1.value, id_eqq, 1, i))) {
53 rb_ary_push(memo->u2.value, i);
54 }
55 return Qnil;
56 }
57
58 static VALUE
59 grep_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
60 {
61 NODE *memo = RNODE(args);
62 ENUM_WANT_SVALUE();
63
64 if (RTEST(rb_funcall(memo->u1.value, id_eqq, 1, i))) {
65 rb_ary_push(memo->u2.value, rb_yield(i));
66 }
67 return Qnil;
68 }
69
70 /*
71 * call-seq:
72 * enum.grep(pattern) -> array
73 * enum.grep(pattern) { |obj| block } -> array
74 *
75 * Returns an array of every element in <i>enum</i> for which
76 * <code>Pattern === element</code>. If the optional <em>block</em> is
77 * supplied, each matching element is passed to it, and the block's
78 * result is stored in the output array.
79 *
80 * (1..100).grep 38..44 #=> [38, 39, 40, 41, 42, 43, 44]
81 * c = IO.constants
82 * c.grep(/SEEK/) #=> [:SEEK_SET, :SEEK_CUR, :SEEK_END]
83 * res = c.grep(/SEEK/) { |v| IO.const_get(v) }
84 * res #=> [0, 1, 2]
85 *
86 */
87
88 static VALUE
89 enum_grep(VALUE obj, VALUE pat)
90 {
91 VALUE ary = rb_ary_new();
92 NODE *memo = NEW_MEMO(pat, ary, 0);
93
94 rb_block_call(obj, id_each, 0, 0, rb_block_given_p() ? grep_iter_i : grep_i, (VALUE)memo);
95
96 return ary;
97 }
98
99 static VALUE
100 count_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
101 {
102 NODE *memo = RNODE(memop);
103
104 ENUM_WANT_SVALUE();
105
106 if (rb_equal(i, memo->u1.value)) {
107 memo->u3.cnt++;
108 }
109 return Qnil;
110 }
111
112 static VALUE
113 count_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
114 {
115 NODE *memo = RNODE(memop);
116
117 if (RTEST(enum_yield(argc, argv))) {
118 memo->u3.cnt++;
119 }
120 return Qnil;
121 }
122
123 static VALUE
124 count_all_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
125 {
126 NODE *memo = RNODE(memop);
127
128 memo->u3.cnt++;
129 return Qnil;
130 }
131
132 /*
133 * call-seq:
134 * enum.count -> int
135 * enum.count(item) -> int
136 * enum.count { |obj| block } -> int
137 *
138 * Returns the number of items in +enum+ through enumeration.
139 * If an argument is given, the number of items in +enum+ that
140 * are equal to +item+ are counted. If a block is given, it
141 * counts the number of elements yielding a true value.
142 *
143 * ary = [1, 2, 4, 2]
144 * ary.count #=> 4
145 * ary.count(2) #=> 2
146 * ary.count{ |x| x%2==0 } #=> 3
147 *
148 */
149
150 static VALUE
151 enum_count(int argc, VALUE *argv, VALUE obj)
152 {
153 VALUE item = Qnil;
154 NODE *memo;
155 rb_block_call_func *func;
156
157 if (argc == 0) {
158 if (rb_block_given_p()) {
159 func = count_iter_i;
160 }
161 else {
162 func = count_all_i;
163 }
164 }
165 else {
166 rb_scan_args(argc, argv, "1", &item);
167 if (rb_block_given_p()) {
168 rb_warn("given block not used");
169 }
170 func = count_i;
171 }
172
173 memo = NEW_MEMO(item, 0, 0);
174 rb_block_call(obj, id_each, 0, 0, func, (VALUE)memo);
175 return INT2NUM(memo->u3.cnt);
176 }
177
178 static VALUE
179 find_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
180 {
181 ENUM_WANT_SVALUE();
182
183 if (RTEST(rb_yield(i))) {
184 NODE *memo = RNODE(memop);
185 memo->u1.value = i;
186 memo->u3.cnt = 1;
187 rb_iter_break();
188 }
189 return Qnil;
190 }
191
192 /*
193 * call-seq:
194 * enum.detect(ifnone = nil) { |obj| block } -> obj or nil
195 * enum.find(ifnone = nil) { |obj| block } -> obj or nil
196 * enum.detect(ifnone = nil) -> an_enumerator
197 * enum.find(ifnone = nil) -> an_enumerator
198 *
199 * Passes each entry in <i>enum</i> to <em>block</em>. Returns the
200 * first for which <em>block</em> is not false. If no
201 * object matches, calls <i>ifnone</i> and returns its result when it
202 * is specified, or returns <code>nil</code> otherwise.
203 *
204 * If no block is given, an enumerator is returned instead.
205 *
206 * (1..10).detect { |i| i % 5 == 0 and i % 7 == 0 } #=> nil
207 * (1..100).find { |i| i % 5 == 0 and i % 7 == 0 } #=> 35
208 *
209 */
210
211 static VALUE
212 enum_find(int argc, VALUE *argv, VALUE obj)
213 {
214 NODE *memo;
215 VALUE if_none;
216
217 rb_scan_args(argc, argv, "01", &if_none);
218 RETURN_ENUMERATOR(obj, argc, argv);
219 memo = NEW_MEMO(Qundef, 0, 0);
220 rb_block_call(obj, id_each, 0, 0, find_i, (VALUE)memo);
221 if (memo->u3.cnt) {
222 return memo->u1.value;
223 }
224 if (!NIL_P(if_none)) {
225 return rb_funcall(if_none, id_call, 0, 0);
226 }
227 return Qnil;
228 }
229
230 static VALUE
231 find_index_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
232 {
233 NODE *memo = RNODE(memop);
234
235 ENUM_WANT_SVALUE();
236
237 if (rb_equal(i, memo->u2.value)) {
238 memo->u1.value = UINT2NUM(memo->u3.cnt);
239 rb_iter_break();
240 }
241 memo->u3.cnt++;
242 return Qnil;
243 }
244
245 static VALUE
246 find_index_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
247 {
248 NODE *memo = RNODE(memop);
249
250 if (RTEST(enum_yield(argc, argv))) {
251 memo->u1.value = UINT2NUM(memo->u3.cnt);
252 rb_iter_break();
253 }
254 memo->u3.cnt++;
255 return Qnil;
256 }
257
258 /*
259 * call-seq:
260 * enum.find_index(value) -> int or nil
261 * enum.find_index { |obj| block } -> int or nil
262 * enum.find_index -> an_enumerator
263 *
264 * Compares each entry in <i>enum</i> with <em>value</em> or passes
265 * to <em>block</em>. Returns the index for the first for which the
266 * evaluated value is non-false. If no object matches, returns
267 * <code>nil</code>
268 *
269 * If neither block nor argument is given, an enumerator is returned instead.
270 *
271 * (1..10).find_index { |i| i % 5 == 0 and i % 7 == 0 } #=> nil
272 * (1..100).find_index { |i| i % 5 == 0 and i % 7 == 0 } #=> 34
273 * (1..100).find_index(50) #=> 49
274 *
275 */
276
277 static VALUE
278 enum_find_index(int argc, VALUE *argv, VALUE obj)
279 {
280 NODE *memo; /* [return value, current index, ] */
281 VALUE condition_value = Qnil;
282 rb_block_call_func *func;
283
284 if (argc == 0) {
285 RETURN_ENUMERATOR(obj, 0, 0);
286 func = find_index_iter_i;
287 }
288 else {
289 rb_scan_args(argc, argv, "1", &condition_value);
290 if (rb_block_given_p()) {
291 rb_warn("given block not used");
292 }
293 func = find_index_i;
294 }
295
296 memo = NEW_MEMO(Qnil, condition_value, 0);
297 rb_block_call(obj, id_each, 0, 0, func, (VALUE)memo);
298 return memo->u1.value;
299 }
300
301 static VALUE
302 find_all_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
303 {
304 ENUM_WANT_SVALUE();
305
306 if (RTEST(rb_yield(i))) {
307 rb_ary_push(ary, i);
308 }
309 return Qnil;
310 }
311
312 static VALUE
313 enum_size(VALUE self, VALUE args, VALUE eobj)
314 {
315 VALUE r;
316 r = rb_check_funcall(self, id_size, 0, 0);
317 return (r == Qundef) ? Qnil : r;
318 }
319
320 /*
321 * call-seq:
322 * enum.find_all { |obj| block } -> array
323 * enum.select { |obj| block } -> array
324 * enum.find_all -> an_enumerator
325 * enum.select -> an_enumerator
326 *
327 * Returns an array containing all elements of +enum+
328 * for which the given +block+ returns a true value.
329 *
330 * If no block is given, an Enumerator is returned instead.
331 *
332 *
333 * (1..10).find_all { |i| i % 3 == 0 } #=> [3, 6, 9]
334 *
335 * [1,2,3,4,5].select { |num| num.even? } #=> [2, 4]
336 *
337 * See also Enumerable#reject.
338 */
339
340 static VALUE
341 enum_find_all(VALUE obj)
342 {
343 VALUE ary;
344
345 RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
346
347 ary = rb_ary_new();
348 rb_block_call(obj, id_each, 0, 0, find_all_i, ary);
349
350 return ary;
351 }
352
353 static VALUE
354 reject_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
355 {
356 ENUM_WANT_SVALUE();
357
358 if (!RTEST(rb_yield(i))) {
359 rb_ary_push(ary, i);
360 }
361 return Qnil;
362 }
363
364 /*
365 * call-seq:
366 * enum.reject { |obj| block } -> array
367 * enum.reject -> an_enumerator
368 *
369 * Returns an array for all elements of +enum+ for which the given
370 * +block+ returns false.
371 *
372 * If no block is given, an Enumerator is returned instead.
373 *
374 * (1..10).reject { |i| i % 3 == 0 } #=> [1, 2, 4, 5, 7, 8, 10]
375 *
376 * [1, 2, 3, 4, 5].reject { |num| num.even? } #=> [1, 3, 5]
377 *
378 * See also Enumerable#find_all.
379 */
380
381 static VALUE
382 enum_reject(VALUE obj)
383 {
384 VALUE ary;
385
386 RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
387
388 ary = rb_ary_new();
389 rb_block_call(obj, id_each, 0, 0, reject_i, ary);
390
391 return ary;
392 }
393
394 static VALUE
395 collect_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
396 {
397 rb_ary_push(ary, enum_yield(argc, argv));
398
399 return Qnil;
400 }
401
402 static VALUE
403 collect_all(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
404 {
405 rb_thread_check_ints();
406 rb_ary_push(ary, rb_enum_values_pack(argc, argv));
407
408 return Qnil;
409 }
410
411 /*
412 * call-seq:
413 * enum.collect { |obj| block } -> array
414 * enum.map { |obj| block } -> array
415 * enum.collect -> an_enumerator
416 * enum.map -> an_enumerator
417 *
418 * Returns a new array with the results of running <em>block</em> once
419 * for every element in <i>enum</i>.
420 *
421 * If no block is given, an enumerator is returned instead.
422 *
423 * (1..4).map { |i| i*i } #=> [1, 4, 9, 16]
424 * (1..4).collect { "cat" } #=> ["cat", "cat", "cat", "cat"]
425 *
426 */
427
428 static VALUE
429 enum_collect(VALUE obj)
430 {
431 VALUE ary;
432
433 RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
434
435 ary = rb_ary_new();
436 rb_block_call(obj, id_each, 0, 0, collect_i, ary);
437
438 return ary;
439 }
440
441 static VALUE
442 flat_map_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
443 {
444 VALUE tmp;
445
446 i = enum_yield(argc, argv);
447 tmp = rb_check_array_type(i);
448
449 if (NIL_P(tmp)) {
450 rb_ary_push(ary, i);
451 }
452 else {
453 rb_ary_concat(ary, tmp);
454 }
455 return Qnil;
456 }
457
458 /*
459 * call-seq:
460 * enum.flat_map { |obj| block } -> array
461 * enum.collect_concat { |obj| block } -> array
462 * enum.flat_map -> an_enumerator
463 * enum.collect_concat -> an_enumerator
464 *
465 * Returns a new array with the concatenated results of running
466 * <em>block</em> once for every element in <i>enum</i>.
467 *
468 * If no block is given, an enumerator is returned instead.
469 *
470 * [1, 2, 3, 4].flat_map { |e| [e, -e] } #=> [1, -1, 2, -2, 3, -3, 4, -4]
471 * [[1, 2], [3, 4]].flat_map { |e| e + [100] } #=> [1, 2, 100, 3, 4, 100]
472 *
473 */
474
475 static VALUE
476 enum_flat_map(VALUE obj)
477 {
478 VALUE ary;
479
480 RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
481
482 ary = rb_ary_new();
483 rb_block_call(obj, id_each, 0, 0, flat_map_i, ary);
484
485 return ary;
486 }
487
488 /*
489 * call-seq:
490 * enum.to_a(*args) -> array
491 * enum.entries(*args) -> array
492 *
493 * Returns an array containing the items in <i>enum</i>.
494 *
495 * (1..7).to_a #=> [1, 2, 3, 4, 5, 6, 7]
496 * { 'a'=>1, 'b'=>2, 'c'=>3 }.to_a #=> [["a", 1], ["b", 2], ["c", 3]]
497 *
498 * require 'prime'
499 * Prime.entries 10 #=> [2, 3, 5, 7]
500 */
501 static VALUE
502 enum_to_a(int argc, VALUE *argv, VALUE obj)
503 {
504 VALUE ary = rb_ary_new();
505
506 rb_block_call(obj, id_each, argc, argv, collect_all, ary);
507 OBJ_INFECT(ary, obj);
508
509 return ary;
510 }
511
512 static VALUE
513 enum_to_h_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash))
514 {
515 VALUE key_value_pair;
516 ENUM_WANT_SVALUE();
517 rb_thread_check_ints();
518 key_value_pair = rb_check_array_type(i);
519 if (NIL_P(key_value_pair)) {
520 rb_raise(rb_eTypeError, "wrong element type %s (expected array)",
521 rb_builtin_class_name(i));
522 }
523 if (RARRAY_LEN(key_value_pair) != 2) {
524 rb_raise(rb_eArgError, "element has wrong array length (expected 2, was %ld)",
525 RARRAY_LEN(key_value_pair));
526 }
527 rb_hash_aset(hash, RARRAY_AREF(key_value_pair, 0), RARRAY_AREF(key_value_pair, 1));
528 return Qnil;
529 }
530
531 /*
532 * call-seq:
533 * enum.to_h(*args) -> hash
534 *
535 * Returns the result of interpreting <i>enum</i> as a list of
536 * <tt>[key, value]</tt> pairs.
537 *
538 * %i[hello world].each_with_index.to_h
539 * # => {:hello => 0, :world => 1}
540 */
541
542 static VALUE
543 enum_to_h(int argc, VALUE *argv, VALUE obj)
544 {
545 VALUE hash = rb_hash_new();
546 rb_block_call(obj, id_each, argc, argv, enum_to_h_i, hash);
547 OBJ_INFECT(hash, obj);
548 return hash;
549 }
550
551 static VALUE
552 inject_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, p))
553 {
554 NODE *memo = RNODE(p);
555
556 ENUM_WANT_SVALUE();
557
558 if (memo->u2.argc == 0) {
559 memo->u2.argc = 1;
560 memo->u1.value = i;
561 }
562 else {
563 memo->u1.value = rb_yield_values(2, memo->u1.value, i);
564 }
565 return Qnil;
566 }
567
568 static VALUE
569 inject_op_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, p))
570 {
571 NODE *memo = RNODE(p);
572 VALUE name;
573
574 ENUM_WANT_SVALUE();
575
576 if (memo->u2.argc == 0) {
577 memo->u2.argc = 1;
578 memo->u1.value = i;
579 }
580 else if (SYMBOL_P(name = memo->u3.value)) {
581 memo->u1.value = rb_funcall(memo->u1.value, SYM2ID(name), 1, i);
582 }
583 else {
584 VALUE args[2];
585 args[0] = name;
586 args[1] = i;
587 memo->u1.value = rb_f_send(numberof(args), args, memo->u1.value);
588 }
589 return Qnil;
590 }
591
592 /*
593 * call-seq:
594 * enum.inject(initial, sym) -> obj
595 * enum.inject(sym) -> obj
596 * enum.inject(initial) { |memo, obj| block } -> obj
597 * enum.inject { |memo, obj| block } -> obj
598 * enum.reduce(initial, sym) -> obj
599 * enum.reduce(sym) -> obj
600 * enum.reduce(initial) { |memo, obj| block } -> obj
601 * enum.reduce { |memo, obj| block } -> obj
602 *
603 * Combines all elements of <i>enum</i> by applying a binary
604 * operation, specified by a block or a symbol that names a
605 * method or operator.
606 *
607 * If you specify a block, then for each element in <i>enum</i>
608 * the block is passed an accumulator value (<i>memo</i>) and the element.
609 * If you specify a symbol instead, then each element in the collection
610 * will be passed to the named method of <i>memo</i>.
611 * In either case, the result becomes the new value for <i>memo</i>.
612 * At the end of the iteration, the final value of <i>memo</i> is the
613 * return value for the method.
614 *
615 * If you do not explicitly specify an <i>initial</i> value for <i>memo</i>,
616 * then the first element of collection is used as the initial value
617 * of <i>memo</i>.
618 *
619 *
620 * # Sum some numbers
621 * (5..10).reduce(:+) #=> 45
622 * # Same using a block and inject
623 * (5..10).inject { |sum, n| sum + n } #=> 45
624 * # Multiply some numbers
625 * (5..10).reduce(1, :*) #=> 151200
626 * # Same using a block
627 * (5..10).inject(1) { |product, n| product * n } #=> 151200
628 * # find the longest word
629 * longest = %w{ cat sheep bear }.inject do |memo, word|
630 * memo.length > word.length ? memo : word
631 * end
632 * longest #=> "sheep"
633 *
634 */
635 static VALUE
636 enum_inject(int argc, VALUE *argv, VALUE obj)
637 {
638 NODE *memo;
639 VALUE init, op;
640 rb_block_call_func *iter = inject_i;
641 ID id;
642
643 switch (rb_scan_args(argc, argv, "02", &init, &op)) {
644 case 0:
645 break;
646 case 1:
647 if (rb_block_given_p()) {
648 break;
649 }
650 id = rb_check_id(&init);
651 op = id ? ID2SYM(id) : init;
652 argc = 0;
653 init = Qnil;
654 iter = inject_op_i;
655 break;
656 case 2:
657 if (rb_block_given_p()) {
658 rb_warning("given block not used");
659 }
660 id = rb_check_id(&op);
661 if (id) op = ID2SYM(id);
662 iter = inject_op_i;
663 break;
664 }
665 memo = NEW_MEMO(init, argc, op);
666 rb_block_call(obj, id_each, 0, 0, iter, (VALUE)memo);
667 return memo->u1.value;
668 }
669
670 static VALUE
671 partition_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, arys))
672 {
673 NODE *memo = RNODE(arys);
674 VALUE ary;
675 ENUM_WANT_SVALUE();
676
677 if (RTEST(rb_yield(i))) {
678 ary = memo->u1.value;
679 }
680 else {
681 ary = memo->u2.value;
682 }
683 rb_ary_push(ary, i);
684 return Qnil;
685 }
686
687 /*
688 * call-seq:
689 * enum.partition { |obj| block } -> [ true_array, false_array ]
690 * enum.partition -> an_enumerator
691 *
692 * Returns two arrays, the first containing the elements of
693 * <i>enum</i> for which the block evaluates to true, the second
694 * containing the rest.
695 *
696 * If no block is given, an enumerator is returned instead.
697 *
698 * (1..6).partition { |v| v.even? } #=> [[2, 4, 6], [1, 3, 5]]
699 *
700 */
701
702 static VALUE
703 enum_partition(VALUE obj)
704 {
705 NODE *memo;
706
707 RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
708
709 memo = NEW_MEMO(rb_ary_new(), rb_ary_new(), 0);
710 rb_block_call(obj, id_each, 0, 0, partition_i, (VALUE)memo);
711
712 return rb_assoc_new(memo->u1.value, memo->u2.value);
713 }
714
715 static VALUE
716 group_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash))
717 {
718 VALUE group;
719 VALUE values;
720
721 ENUM_WANT_SVALUE();
722
723 group = rb_yield(i);
724 values = rb_hash_aref(hash, group);
725 if (!RB_TYPE_P(values, T_ARRAY)) {
726 values = rb_ary_new3(1, i);
727 rb_hash_aset(hash, group, values);
728 }
729 else {
730 rb_ary_push(values, i);
731 }
732 return Qnil;
733 }
734
735 /*
736 * call-seq:
737 * enum.group_by { |obj| block } -> a_hash
738 * enum.group_by -> an_enumerator
739 *
740 * Groups the collection by result of the block. Returns a hash where the
741 * keys are the evaluated result from the block and the values are
742 * arrays of elements in the collection that correspond to the key.
743 *
744 * If no block is given an enumerator is returned.
745 *
746 * (1..6).group_by { |i| i%3 } #=> {0=>[3, 6], 1=>[1, 4], 2=>[2, 5]}
747 *
748 */
749
750 static VALUE
751 enum_group_by(VALUE obj)
752 {
753 VALUE hash;
754
755 RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
756
757 hash = rb_hash_new();
758 rb_block_call(obj, id_each, 0, 0, group_by_i, hash);
759 OBJ_INFECT(hash, obj);
760
761 return hash;
762 }
763
764 static VALUE
765 first_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, params))
766 {
767 NODE *memo = RNODE(params);
768 ENUM_WANT_SVALUE();
769
770 memo->u1.value = i;
771 rb_iter_break();
772
773 UNREACHABLE;
774 }
775
776 static VALUE enum_take(VALUE obj, VALUE n);
777
778 /*
779 * call-seq:
780 * enum.first -> obj or nil
781 * enum.first(n) -> an_array
782 *
783 * Returns the first element, or the first +n+ elements, of the enumerable.
784 * If the enumerable is empty, the first form returns <code>nil</code>, and the
785 * second form returns an empty array.
786 *
787 * %w[foo bar baz].first #=> "foo"
788 * %w[foo bar baz].first(2) #=> ["foo", "bar"]
789 * %w[foo bar baz].first(10) #=> ["foo", "bar", "baz"]
790 * [].first #=> nil
791 *
792 */
793
794 static VALUE
795 enum_first(int argc, VALUE *argv, VALUE obj)
796 {
797 NODE *memo;
798 rb_check_arity(argc, 0, 1);
799 if (argc > 0) {
800 return enum_take(obj, argv[0]);
801 }
802 else {
803 memo = NEW_MEMO(Qnil, 0, 0);
804 rb_block_call(obj, id_each, 0, 0, first_i, (VALUE)memo);
805 return memo->u1.value;
806 }
807 }
808
809
810 /*
811 * call-seq:
812 * enum.sort -> array
813 * enum.sort { |a, b| block } -> array
814 *
815 * Returns an array containing the items in <i>enum</i> sorted,
816 * either according to their own <code><=></code> method, or by using
817 * the results of the supplied block. The block should return -1, 0, or
818 * +1 depending on the comparison between <i>a</i> and <i>b</i>. As of
819 * Ruby 1.8, the method <code>Enumerable#sort_by</code> implements a
820 * built-in Schwartzian Transform, useful when key computation or
821 * comparison is expensive.
822 *
823 * %w(rhea kea flea).sort #=> ["flea", "kea", "rhea"]
824 * (1..10).sort { |a, b| b <=> a } #=> [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
825 */
826
827 static VALUE
828 enum_sort(VALUE obj)
829 {
830 return rb_ary_sort(enum_to_a(0, 0, obj));
831 }
832
833 #define SORT_BY_BUFSIZE 16
834 struct sort_by_data {
835 VALUE ary;
836 VALUE buf;
837 long n;
838 };
839
840 static VALUE
841 sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, _data))
842 {
843 struct sort_by_data *data = (struct sort_by_data *)&RNODE(_data)->u1;
844 VALUE ary = data->ary;
845 VALUE v;
846
847 ENUM_WANT_SVALUE();
848
849 v = rb_yield(i);
850
851 if (RBASIC(ary)->klass) {
852 rb_raise(rb_eRuntimeError, "sort_by reentered");
853 }
854 if (RARRAY_LEN(data->buf) != SORT_BY_BUFSIZE*2) {
855 rb_raise(rb_eRuntimeError, "sort_by reentered");
856 }
857
858 RARRAY_ASET(data->buf, data->n*2, v);
859 RARRAY_ASET(data->buf, data->n*2+1, i);
860 data->n++;
861 if (data->n == SORT_BY_BUFSIZE) {
862 rb_ary_concat(ary, data->buf);
863 data->n = 0;
864 }
865 return Qnil;
866 }
867
868 static int
869 sort_by_cmp(const void *ap, const void *bp, void *data)
870 {
871 VALUE a;
872 VALUE b;
873 VALUE ary = (VALUE)data;
874
875 if (RBASIC(ary)->klass) {
876 rb_raise(rb_eRuntimeError, "sort_by reentered");
877 }
878
879 a = *(VALUE *)ap;
880 b = *(VALUE *)bp;
881
882 return rb_cmpint(rb_funcall(a, id_cmp, 1, b), a, b);
883 }
884
885 /*
886 * call-seq:
887 * enum.sort_by { |obj| block } -> array
888 * enum.sort_by -> an_enumerator
889 *
890 * Sorts <i>enum</i> using a set of keys generated by mapping the
891 * values in <i>enum</i> through the given block.
892 *
893 * If no block is given, an enumerator is returned instead.
894 *
895 * %w{apple pear fig}.sort_by { |word| word.length}
896 * #=> ["fig", "pear", "apple"]
897 *
898 * The current implementation of <code>sort_by</code> generates an
899 * array of tuples containing the original collection element and the
900 * mapped value. This makes <code>sort_by</code> fairly expensive when
901 * the keysets are simple.
902 *
903 * require 'benchmark'
904 *
905 * a = (1..100000).map { rand(100000) }
906 *
907 * Benchmark.bm(10) do |b|
908 * b.report("Sort") { a.sort }
909 * b.report("Sort by") { a.sort_by { |a| a } }
910 * end
911 *
912 * <em>produces:</em>
913 *
914 * user system total real
915 * Sort 0.180000 0.000000 0.180000 ( 0.175469)
916 * Sort by 1.980000 0.040000 2.020000 ( 2.013586)
917 *
918 * However, consider the case where comparing the keys is a non-trivial
919 * operation. The following code sorts some files on modification time
920 * using the basic <code>sort</code> method.
921 *
922 * files = Dir["*"]
923 * sorted = files.sort { |a, b| File.new(a).mtime <=> File.new(b).mtime }
924 * sorted #=> ["mon", "tues", "wed", "thurs"]
925 *
926 * This sort is inefficient: it generates two new <code>File</code>
927 * objects during every comparison. A slightly better technique is to
928 * use the <code>Kernel#test</code> method to generate the modification
929 * times directly.
930 *
931 * files = Dir["*"]
932 * sorted = files.sort { |a, b|
933 * test(?M, a) <=> test(?M, b)
934 * }
935 * sorted #=> ["mon", "tues", "wed", "thurs"]
936 *
937 * This still generates many unnecessary <code>Time</code> objects. A
938 * more efficient technique is to cache the sort keys (modification
939 * times in this case) before the sort. Perl users often call this
940 * approach a Schwartzian Transform, after Randal Schwartz. We
941 * construct a temporary array, where each element is an array
942 * containing our sort key along with the filename. We sort this array,
943 * and then extract the filename from the result.
944 *
945 * sorted = Dir["*"].collect { |f|
946 * [test(?M, f), f]
947 * }.sort.collect { |f| f[1] }
948 * sorted #=> ["mon", "tues", "wed", "thurs"]
949 *
950 * This is exactly what <code>sort_by</code> does internally.
951 *
952 * sorted = Dir["*"].sort_by { |f| test(?M, f) }
953 * sorted #=> ["mon", "tues", "wed", "thurs"]
954 */
955
956 static VALUE
957 enum_sort_by(VALUE obj)
958 {
959 VALUE ary, buf;
960 NODE *memo;
961 long i;
962 struct sort_by_data *data;
963
964 RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
965
966 if (RB_TYPE_P(obj, T_ARRAY) && RARRAY_LEN(obj) <= LONG_MAX/2) {
967 ary = rb_ary_new2(RARRAY_LEN(obj)*2);
968 }
969 else {
970 ary = rb_ary_new();
971 }
972 RBASIC_CLEAR_CLASS(ary);
973 buf = rb_ary_tmp_new(SORT_BY_BUFSIZE*2);
974 rb_ary_store(buf, SORT_BY_BUFSIZE*2-1, Qnil);
975 memo = NEW_MEMO(0, 0, 0);
976 OBJ_INFECT(memo, obj);
977 data = (struct sort_by_data *)&memo->u1;
978 data->ary = ary;
979 data->buf = buf;
980 data->n = 0;
981 rb_block_call(obj, id_each, 0, 0, sort_by_i, (VALUE)memo);
982 ary = data->ary;
983 buf = data->buf;
984 if (data->n) {
985 rb_ary_resize(buf, data->n*2);
986 rb_ary_concat(ary, buf);
987 }
988 if (RARRAY_LEN(ary) > 2) {
989 RARRAY_PTR_USE(ary, ptr,
990 ruby_qsort(ptr, RARRAY_LEN(ary)/2, 2*sizeof(VALUE),
991 sort_by_cmp, (void *)ary));
992 }
993 if (RBASIC(ary)->klass) {
994 rb_raise(rb_eRuntimeError, "sort_by reentered");
995 }
996 for (i=1; i<RARRAY_LEN(ary); i+=2) {
997 RARRAY_ASET(ary, i/2, RARRAY_AREF(ary, i));
998 }
999 rb_ary_resize(ary, RARRAY_LEN(ary)/2);
1000 RBASIC_SET_CLASS_RAW(ary, rb_cArray);
1001 OBJ_INFECT(ary, memo);
1002
1003 return ary;
1004 }
1005
1006 #define ENUMFUNC(name) rb_block_given_p() ? name##_iter_i : name##_i
1007
1008 #define DEFINE_ENUMFUNCS(name) \
1009 static VALUE enum_##name##_func(VALUE result, NODE *memo); \
1010 \
1011 static VALUE \
1012 name##_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo)) \
1013 { \
1014 return enum_##name##_func(rb_enum_values_pack(argc, argv), RNODE(memo)); \
1015 } \
1016 \
1017 static VALUE \
1018 name##_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo)) \
1019 { \
1020 return enum_##name##_func(enum_yield(argc, argv), RNODE(memo)); \
1021 } \
1022 \
1023 static VALUE \
1024 enum_##name##_func(VALUE result, NODE *memo)
1025
1026 DEFINE_ENUMFUNCS(all)
1027 {
1028 if (!RTEST(result)) {
1029 memo->u1.value = Qfalse;
1030 rb_iter_break();
1031 }
1032 return Qnil;
1033 }
1034
1035 /*
1036 * call-seq:
1037 * enum.all? [{ |obj| block } ] -> true or false
1038 *
1039 * Passes each element of the collection to the given block. The method
1040 * returns <code>true</code> if the block never returns
1041 * <code>false</code> or <code>nil</code>. If the block is not given,
1042 * Ruby adds an implicit block of <code>{ |obj| obj }</code> which will
1043 * cause #all? to return +true+ when none of the collection members are
1044 * +false+ or +nil+.
1045 *
1046 * %w[ant bear cat].all? { |word| word.length >= 3 } #=> true
1047 * %w[ant bear cat].all? { |word| word.length >= 4 } #=> false
1048 * [nil, true, 99].all? #=> false
1049 *
1050 */
1051
1052 static VALUE
1053 enum_all(VALUE obj)
1054 {
1055 NODE *memo = NEW_MEMO(Qtrue, 0, 0);
1056 rb_block_call(obj, id_each, 0, 0, ENUMFUNC(all), (VALUE)memo);
1057 return memo->u1.value;
1058 }
1059
1060 DEFINE_ENUMFUNCS(any)
1061 {
1062 if (RTEST(result)) {
1063 memo->u1.value = Qtrue;
1064 rb_iter_break();
1065 }
1066 return Qnil;
1067 }
1068
1069 /*
1070 * call-seq:
1071 * enum.any? [{ |obj| block }] -> true or false
1072 *
1073 * Passes each element of the collection to the given block. The method
1074 * returns <code>true</code> if the block ever returns a value other
1075 * than <code>false</code> or <code>nil</code>. If the block is not
1076 * given, Ruby adds an implicit block of <code>{ |obj| obj }</code> that
1077 * will cause #any? to return +true+ if at least one of the collection
1078 * members is not +false+ or +nil+.
1079 *
1080 * %w[ant bear cat].any? { |word| word.length >= 3 } #=> true
1081 * %w[ant bear cat].any? { |word| word.length >= 4 } #=> true
1082 * [nil, true, 99].any? #=> true
1083 *
1084 */
1085
1086 static VALUE
1087 enum_any(VALUE obj)
1088 {
1089 NODE *memo = NEW_MEMO(Qfalse, 0, 0);
1090 rb_block_call(obj, id_each, 0, 0, ENUMFUNC(any), (VALUE)memo);
1091 return memo->u1.value;
1092 }
1093
1094 DEFINE_ENUMFUNCS(one)
1095 {
1096 if (RTEST(result)) {
1097 if (memo->u1.value == Qundef) {
1098 memo->u1.value = Qtrue;
1099 }
1100 else if (memo->u1.value == Qtrue) {
1101 memo->u1.value = Qfalse;
1102 rb_iter_break();
1103 }
1104 }
1105 return Qnil;
1106 }
1107
1108 /*
1109 * call-seq:
1110 * enum.one? [{ |obj| block }] -> true or false
1111 *
1112 * Passes each element of the collection to the given block. The method
1113 * returns <code>true</code> if the block returns <code>true</code>
1114 * exactly once. If the block is not given, <code>one?</code> will return
1115 * <code>true</code> only if exactly one of the collection members is
1116 * true.
1117 *
1118 * %w{ant bear cat}.one? { |word| word.length == 4 } #=> true
1119 * %w{ant bear cat}.one? { |word| word.length > 4 } #=> false
1120 * %w{ant bear cat}.one? { |word| word.length < 4 } #=> false
1121 * [ nil, true, 99 ].one? #=> false
1122 * [ nil, true, false ].one? #=> true
1123 *
1124 */
1125
1126 static VALUE
1127 enum_one(VALUE obj)
1128 {
1129 NODE *memo = NEW_MEMO(Qundef, 0, 0);
1130 VALUE result;
1131
1132 rb_block_call(obj, id_each, 0, 0, ENUMFUNC(one), (VALUE)memo);
1133 result = memo->u1.value;
1134 if (result == Qundef) return Qfalse;
1135 return result;
1136 }
1137
1138 DEFINE_ENUMFUNCS(none)
1139 {
1140 if (RTEST(result)) {
1141 memo->u1.value = Qfalse;
1142 rb_iter_break();
1143 }
1144 return Qnil;
1145 }
1146
1147 /*
1148 * call-seq:
1149 * enum.none? [{ |obj| block }] -> true or false
1150 *
1151 * Passes each element of the collection to the given block. The method
1152 * returns <code>true</code> if the block never returns <code>true</code>
1153 * for all elements. If the block is not given, <code>none?</code> will return
1154 * <code>true</code> only if none of the collection members is true.
1155 *
1156 * %w{ant bear cat}.none? { |word| word.length == 5 } #=> true
1157 * %w{ant bear cat}.none? { |word| word.length >= 4 } #=> false
1158 * [].none? #=> true
1159 * [nil].none? #=> true
1160 * [nil, false].none? #=> true
1161 */
1162 static VALUE
1163 enum_none(VALUE obj)
1164 {
1165 NODE *memo = NEW_MEMO(Qtrue, 0, 0);
1166 rb_block_call(obj, id_each, 0, 0, ENUMFUNC(none), (VALUE)memo);
1167 return memo->u1.value;
1168 }
1169
1170 static VALUE
1171 min_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
1172 {
1173 VALUE cmp;
1174 NODE *memo = RNODE(args);
1175
1176 ENUM_WANT_SVALUE();
1177
1178 if (memo->u1.value == Qundef) {
1179 memo->u1.value = i;
1180 }
1181 else {
1182 cmp = rb_funcall(i, id_cmp, 1, memo->u1.value);
1183 if (rb_cmpint(cmp, i, memo->u1.value) < 0) {
1184 memo->u1.value = i;
1185 }
1186 }
1187 return Qnil;
1188 }
1189
1190 static VALUE
1191 min_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
1192 {
1193 VALUE cmp;
1194 NODE *memo = RNODE(args);
1195
1196 ENUM_WANT_SVALUE();
1197
1198 if (memo->u1.value == Qundef) {
1199 memo->u1.value = i;
1200 }
1201 else {
1202 cmp = rb_yield_values(2, i, memo->u1.value);
1203 if (rb_cmpint(cmp, i, memo->u1.value) < 0) {
1204 memo->u1.value = i;
1205 }
1206 }
1207 return Qnil;
1208 }
1209
1210
1211 /*
1212 * call-seq:
1213 * enum.min -> obj
1214 * enum.min { |a, b| block } -> obj
1215 *
1216 * Returns the object in <i>enum</i> with the minimum value. The
1217 * first form assumes all objects implement <code>Comparable</code>;
1218 * the second uses the block to return <em>a <=> b</em>.
1219 *
1220 * a = %w(albatross dog horse)
1221 * a.min #=> "albatross"
1222 * a.min { |a, b| a.length <=> b.length } #=> "dog"
1223 */
1224
1225 static VALUE
1226 enum_min(VALUE obj)
1227 {
1228 NODE *memo = NEW_MEMO(Qundef, 0, 0);
1229 VALUE result;
1230
1231 if (rb_block_given_p()) {
1232 rb_block_call(obj, id_each, 0, 0, min_ii, (VALUE)memo);
1233 }
1234 else {
1235 rb_block_call(obj, id_each, 0, 0, min_i, (VALUE)memo);
1236 }
1237 result = memo->u1.value;
1238 if (result == Qundef) return Qnil;
1239 return result;
1240 }
1241
1242 static VALUE
1243 max_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
1244 {
1245 NODE *memo = RNODE(args);
1246 VALUE cmp;
1247
1248 ENUM_WANT_SVALUE();
1249
1250 if (memo->u1.value == Qundef) {
1251 memo->u1.value = i;
1252 }
1253 else {
1254 cmp = rb_funcall(i, id_cmp, 1, memo->u1.value);
1255 if (rb_cmpint(cmp, i, memo->u1.value) > 0) {
1256 memo->u1.value = i;
1257 }
1258 }
1259 return Qnil;
1260 }
1261
1262 static VALUE
1263 max_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
1264 {
1265 NODE *memo = RNODE(args);
1266 VALUE cmp;
1267
1268 ENUM_WANT_SVALUE();
1269
1270 if (memo->u1.value == Qundef) {
1271 memo->u1.value = i;
1272 }
1273 else {
1274 cmp = rb_yield_values(2, i, memo->u1.value);
1275 if (rb_cmpint(cmp, i, memo->u1.value) > 0) {
1276 memo->u1.value = i;
1277 }
1278 }
1279 return Qnil;
1280 }
1281
1282 /*
1283 * call-seq:
1284 * enum.max -> obj
1285 * enum.max { |a, b| block } -> obj
1286 *
1287 * Returns the object in _enum_ with the maximum value. The
1288 * first form assumes all objects implement <code>Comparable</code>;
1289 * the second uses the block to return <em>a <=> b</em>.
1290 *
1291 * a = %w(albatross dog horse)
1292 * a.max #=> "horse"
1293 * a.max { |a, b| a.length <=> b.length } #=> "albatross"
1294 */
1295
1296 static VALUE
1297 enum_max(VALUE obj)
1298 {
1299 NODE *memo = NEW_MEMO(Qundef, 0, 0);
1300 VALUE result;
1301
1302 if (rb_block_given_p()) {
1303 rb_block_call(obj, id_each, 0, 0, max_ii, (VALUE)memo);
1304 }
1305 else {
1306 rb_block_call(obj, id_each, 0, 0, max_i, (VALUE)memo);
1307 }
1308 result = memo->u1.value;
1309 if (result == Qundef) return Qnil;
1310 return result;
1311 }
1312
1313 struct minmax_t {
1314 VALUE min;
1315 VALUE max;
1316 VALUE last;
1317 };
1318
1319 STATIC_ASSERT(minmax_t, sizeof(struct minmax_t) <= sizeof(NODE) - offsetof(NODE, u1));
1320
1321 static void
1322 minmax_i_update(VALUE i, VALUE j, struct minmax_t *memo)
1323 {
1324 int n;
1325
1326 if (memo->min == Qundef) {
1327 memo->min = i;
1328 memo->max = j;
1329 }
1330 else {
1331 n = rb_cmpint(rb_funcall(i, id_cmp, 1, memo->min), i, memo->min);
1332 if (n < 0) {
1333 memo->min = i;
1334 }
1335 n = rb_cmpint(rb_funcall(j, id_cmp, 1, memo->max), j, memo->max);
1336 if (n > 0) {
1337 memo->max = j;
1338 }
1339 }
1340 }
1341
1342 static VALUE
1343 minmax_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo))
1344 {
1345 struct minmax_t *memo = (struct minmax_t *)&RNODE(_memo)->u1.value;
1346 int n;
1347 VALUE j;
1348
1349 ENUM_WANT_SVALUE();
1350
1351 if (memo->last == Qundef) {
1352 memo->last = i;
1353 return Qnil;
1354 }
1355 j = memo->last;
1356 memo->last = Qundef;
1357
1358 n = rb_cmpint(rb_funcall(j, id_cmp, 1, i), j, i);
1359 if (n == 0)
1360 i = j;
1361 else if (n < 0) {
1362 VALUE tmp;
1363 tmp = i;
1364 i = j;
1365 j = tmp;
1366 }
1367
1368 minmax_i_update(i, j, memo);
1369
1370 return Qnil;
1371 }
1372
1373 static void
1374 minmax_ii_update(VALUE i, VALUE j, struct minmax_t *memo)
1375 {
1376 int n;
1377
1378 if (memo->min == Qundef) {
1379 memo->min = i;
1380 memo->max = j;
1381 }
1382 else {
1383 n = rb_cmpint(rb_yield_values(2, i, memo->min), i, memo->min);
1384 if (n < 0) {
1385 memo->min = i;
1386 }
1387 n = rb_cmpint(rb_yield_values(2, j, memo->max), j, memo->max);
1388 if (n > 0) {
1389 memo->max = j;
1390 }
1391 }
1392 }
1393
1394 static VALUE
1395 minmax_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo))
1396 {
1397 struct minmax_t *memo = (struct minmax_t *)&RNODE(_memo)->u1.value;
1398 int n;
1399 VALUE j;
1400
1401 ENUM_WANT_SVALUE();
1402
1403 if (memo->last == Qundef) {
1404 memo->last = i;
1405 return Qnil;
1406 }
1407 j = memo->last;
1408 memo->last = Qundef;
1409
1410 n = rb_cmpint(rb_yield_values(2, j, i), j, i);
1411 if (n == 0)
1412 i = j;
1413 else if (n < 0) {
1414 VALUE tmp;
1415 tmp = i;
1416 i = j;
1417 j = tmp;
1418 }
1419
1420 minmax_ii_update(i, j, memo);
1421
1422 return Qnil;
1423 }
1424
1425 /*
1426 * call-seq:
1427 * enum.minmax -> [min, max]
1428 * enum.minmax { |a, b| block } -> [min, max]
1429 *
1430 * Returns two elements array which contains the minimum and the
1431 * maximum value in the enumerable. The first form assumes all
1432 * objects implement <code>Comparable</code>; the second uses the
1433 * block to return <em>a <=> b</em>.
1434 *
1435 * a = %w(albatross dog horse)
1436 * a.minmax #=> ["albatross", "horse"]
1437 * a.minmax { |a, b| a.length <=> b.length } #=> ["dog", "albatross"]
1438 */
1439
1440 static VALUE
1441 enum_minmax(VALUE obj)
1442 {
1443 NODE *memo = NEW_MEMO(Qundef, Qundef, Qundef);
1444 struct minmax_t *m = (struct minmax_t *)&memo->u1.value;
1445 VALUE ary = rb_ary_new3(2, Qnil, Qnil);
1446
1447 m->min = Qundef;
1448 m->last = Qundef;
1449 if (rb_block_given_p()) {
1450 rb_block_call(obj, id_each, 0, 0, minmax_ii, (VALUE)memo);
1451 if (m->last != Qundef)
1452 minmax_ii_update(m->last, m->last, m);
1453 }
1454 else {
1455 rb_block_call(obj, id_each, 0, 0, minmax_i, (VALUE)memo);
1456 if (m->last != Qundef)
1457 minmax_i_update(m->last, m->last, m);
1458 }
1459 if (m->min != Qundef) {
1460 rb_ary_store(ary, 0, m->min);
1461 rb_ary_store(ary, 1, m->max);
1462 }
1463 return ary;
1464 }
1465
1466 static VALUE
1467 min_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
1468 {
1469 NODE *memo = RNODE(args);
1470 VALUE v;
1471
1472 ENUM_WANT_SVALUE();
1473
1474 v = rb_yield(i);
1475 if (memo->u1.value == Qundef) {
1476 memo->u1.value = v;
1477 memo->u2.value = i;
1478 }
1479 else if (rb_cmpint(rb_funcall(v, id_cmp, 1, memo->u1.value), v, memo->u1.value) < 0) {
1480 memo->u1.value = v;
1481 memo->u2.value = i;
1482 }
1483 return Qnil;
1484 }
1485
1486 /*
1487 * call-seq:
1488 * enum.min_by { |obj| block } -> obj
1489 * enum.min_by -> an_enumerator
1490 *
1491 * Returns the object in <i>enum</i> that gives the minimum
1492 * value from the given block.
1493 *
1494 * If no block is given, an enumerator is returned instead.
1495 *
1496 * a = %w(albatross dog horse)
1497 * a.min_by { |x| x.length } #=> "dog"
1498 */
1499
1500 static VALUE
1501 enum_min_by(VALUE obj)
1502 {
1503 NODE *memo;
1504
1505 RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
1506
1507 memo = NEW_MEMO(Qundef, Qnil, 0);
1508 rb_block_call(obj, id_each, 0, 0, min_by_i, (VALUE)memo);
1509 return memo->u2.value;
1510 }
1511
1512 static VALUE
1513 max_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
1514 {
1515 NODE *memo = RNODE(args);
1516 VALUE v;
1517
1518 ENUM_WANT_SVALUE();
1519
1520 v = rb_yield(i);
1521 if (memo->u1.value == Qundef) {
1522 memo->u1.value = v;
1523 memo->u2.value = i;
1524 }
1525 else if (rb_cmpint(rb_funcall(v, id_cmp, 1, memo->u1.value), v, memo->u1.value) > 0) {
1526 memo->u1.value = v;
1527 memo->u2.value = i;
1528 }
1529 return Qnil;
1530 }
1531
1532 /*
1533 * call-seq:
1534 * enum.max_by { |obj| block } -> obj
1535 * enum.max_by -> an_enumerator
1536 *
1537 * Returns the object in <i>enum</i> that gives the maximum
1538 * value from the given block.
1539 *
1540 * If no block is given, an enumerator is returned instead.
1541 *
1542 * a = %w(albatross dog horse)
1543 * a.max_by { |x| x.length } #=> "albatross"
1544 */
1545
1546 static VALUE
1547 enum_max_by(VALUE obj)
1548 {
1549 NODE *memo;
1550
1551 RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
1552
1553 memo = NEW_MEMO(Qundef, Qnil, 0);
1554 rb_block_call(obj, id_each, 0, 0, max_by_i, (VALUE)memo);
1555 return memo->u2.value;
1556 }
1557
1558 struct minmax_by_t {
1559 VALUE min_bv;
1560 VALUE max_bv;
1561 VALUE min;
1562 VALUE max;
1563 VALUE last_bv;
1564 VALUE last;
1565 };
1566
1567 static void
1568 minmax_by_i_update(VALUE v1, VALUE v2, VALUE i1, VALUE i2, struct minmax_by_t *memo)
1569 {
1570 if (memo->min_bv == Qundef) {
1571 memo->min_bv = v1;
1572 memo->max_bv = v2;
1573 memo->min = i1;
1574 memo->max = i2;
1575 }
1576 else {
1577 if (rb_cmpint(rb_funcall(v1, id_cmp, 1, memo->min_bv), v1, memo->min_bv) < 0) {
1578 memo->min_bv = v1;
1579 memo->min = i1;
1580 }
1581 if (rb_cmpint(rb_funcall(v2, id_cmp, 1, memo->max_bv), v2, memo->max_bv) > 0) {
1582 memo->max_bv = v2;
1583 memo->max = i2;
1584 }
1585 }
1586 }
1587
1588 static VALUE
1589 minmax_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo))
1590 {
1591 struct minmax_by_t *memo = MEMO_FOR(struct minmax_by_t, _memo);
1592 VALUE vi, vj, j;
1593 int n;
1594
1595 ENUM_WANT_SVALUE();
1596
1597 vi = rb_yield(i);
1598
1599 if (memo->last_bv == Qundef) {
1600 memo->last_bv = vi;
1601 memo->last = i;
1602 return Qnil;
1603 }
1604 vj = memo->last_bv;
1605 j = memo->last;
1606 memo->last_bv = Qundef;
1607
1608 n = rb_cmpint(rb_funcall(vj, id_cmp, 1, vi), vj, vi);
1609 if (n == 0) {
1610 i = j;
1611 vi = vj;
1612 }
1613 else if (n < 0) {
1614 VALUE tmp;
1615 tmp = i;
1616 i = j;
1617 j = tmp;
1618 tmp = vi;
1619 vi = vj;
1620 vj = tmp;
1621 }
1622
1623 minmax_by_i_update(vi, vj, i, j, memo);
1624
1625 return Qnil;
1626 }
1627
1628 /*
1629 * call-seq:
1630 * enum.minmax_by { |obj| block } -> [min, max]
1631 * enum.minmax_by -> an_enumerator
1632 *
1633 * Returns a two element array containing the objects in
1634 * <i>enum</i> that correspond to the minimum and maximum values respectively
1635 * from the given block.
1636 *
1637 * If no block is given, an enumerator is returned instead.
1638 *
1639 * a = %w(albatross dog horse)
1640 * a.minmax_by { |x| x.length } #=> ["dog", "albatross"]
1641 */
1642
1643 static VALUE
1644 enum_minmax_by(VALUE obj)
1645 {
1646 VALUE memo;
1647 struct minmax_by_t *m = NEW_MEMO_FOR(struct minmax_by_t, memo);
1648
1649 RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
1650
1651 m->min_bv = Qundef;
1652 m->max_bv = Qundef;
1653 m->min = Qnil;
1654 m->max = Qnil;
1655 m->last_bv = Qundef;
1656 m->last = Qundef;
1657 rb_block_call(obj, id_each, 0, 0, minmax_by_i, memo);
1658 if (m->last_bv != Qundef)
1659 minmax_by_i_update(m->last_bv, m->last_bv, m->last, m->last, m);
1660 m = MEMO_FOR(struct minmax_by_t, memo);
1661 return rb_assoc_new(m->min, m->max);
1662 }
1663
1664 static VALUE
1665 member_i(RB_BLOCK_CALL_FUNC_ARGLIST(iter, args))
1666 {
1667 NODE *memo = RNODE(args);
1668
1669 if (rb_equal(rb_enum_values_pack(argc, argv), memo->u1.value)) {
1670 memo->u2.value = Qtrue;
1671 rb_iter_break();
1672 }
1673 return Qnil;
1674 }
1675
1676 /*
1677 * call-seq:
1678 * enum.include?(obj) -> true or false
1679 * enum.member?(obj) -> true or false
1680 *
1681 * Returns <code>true</code> if any member of <i>enum</i> equals
1682 * <i>obj</i>. Equality is tested using <code>==</code>.
1683 *
1684 * IO.constants.include? :SEEK_SET #=> true
1685 * IO.constants.include? :SEEK_NO_FURTHER #=> false
1686 *
1687 */
1688
1689 static VALUE
1690 enum_member(VALUE obj, VALUE val)
1691 {
1692 NODE *memo = NEW_MEMO(val, Qfalse, 0);
1693
1694 rb_block_call(obj, id_each, 0, 0, member_i, (VALUE)memo);
1695 return memo->u2.value;
1696 }
1697
1698 static VALUE
1699 each_with_index_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo))
1700 {
1701 long n = RNODE(memo)->u3.cnt++;
1702
1703 return rb_yield_values(2, rb_enum_values_pack(argc, argv), INT2NUM(n));
1704 }
1705
1706 /*
1707 * call-seq:
1708 * enum.each_with_index(*args) { |obj, i| block } -> enum
1709 * enum.each_with_index(*args) -> an_enumerator
1710 *
1711 * Calls <em>block</em> with two arguments, the item and its index,
1712 * for each item in <i>enum</i>. Given arguments are passed through
1713 * to #each().
1714 *
1715 * If no block is given, an enumerator is returned instead.
1716 *
1717 * hash = Hash.new
1718 * %w(cat dog wombat).each_with_index { |item, index|
1719 * hash[item] = index
1720 * }
1721 * hash #=> {"cat"=>0, "dog"=>1, "wombat"=>2}
1722 *
1723 */
1724
1725 static VALUE
1726 enum_each_with_index(int argc, VALUE *argv, VALUE obj)
1727 {
1728 NODE *memo;
1729
1730 RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size);
1731
1732 memo = NEW_MEMO(0, 0, 0);
1733 rb_block_call(obj, id_each, argc, argv, each_with_index_i, (VALUE)memo);
1734 return obj;
1735 }
1736
1737
1738 /*
1739 * call-seq:
1740 * enum.reverse_each(*args) { |item| block } -> enum
1741 * enum.reverse_each(*args) -> an_enumerator
1742 *
1743 * Builds a temporary array and traverses that array in reverse order.
1744 *
1745 * If no block is given, an enumerator is returned instead.
1746 *
1747 * (1..3).reverse_each { |v| p v }
1748 *
1749 * produces:
1750 *
1751 * 3
1752 * 2
1753 * 1
1754 */
1755
1756 static VALUE
1757 enum_reverse_each(int argc, VALUE *argv, VALUE obj)
1758 {
1759 VALUE ary;
1760 long i;
1761
1762 RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size);
1763
1764 ary = enum_to_a(argc, argv, obj);
1765
1766 for (i = RARRAY_LEN(ary); --i >= 0; ) {
1767 rb_yield(RARRAY_AREF(ary, i));
1768 }
1769
1770 return obj;
1771 }
1772
1773
1774 static VALUE
1775 each_val_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, p))
1776 {
1777 ENUM_WANT_SVALUE();
1778 rb_yield(i);
1779 return Qnil;
1780 }
1781
1782 /*
1783 * call-seq:
1784 * enum.each_entry { |obj| block } -> enum
1785 * enum.each_entry -> an_enumerator
1786 *
1787 * Calls <i>block</i> once for each element in +self+, passing that
1788 * element as a parameter, converting multiple values from yield to an
1789 * array.
1790 *
1791 * If no block is given, an enumerator is returned instead.
1792 *
1793 * class Foo
1794 * include Enumerable
1795 * def each
1796 * yield 1
1797 * yield 1, 2
1798 * yield
1799 * end
1800 * end
1801 * Foo.new.each_entry{ |o| p o }
1802 *
1803 * produces:
1804 *
1805 * 1
1806 * [1, 2]
1807 * nil
1808 *
1809 */
1810
1811 static VALUE
1812 enum_each_entry(int argc, VALUE *argv, VALUE obj)
1813 {
1814 RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size);
1815 rb_block_call(obj, id_each, argc, argv, each_val_i, 0);
1816 return obj;
1817 }
1818
1819 static VALUE
1820 each_slice_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, m))
1821 {
1822 NODE *memo = RNODE(m);
1823 VALUE ary = memo->u1.value;
1824 VALUE v = Qnil;
1825 long size = memo->u3.cnt;
1826 ENUM_WANT_SVALUE();
1827
1828 rb_ary_push(ary, i);
1829
1830 if (RARRAY_LEN(ary) == size) {
1831 v = rb_yield(ary);
1832 memo->u1.value = rb_ary_new2(size);
1833 }
1834
1835 return v;
1836 }
1837
1838 static VALUE
1839 enum_each_slice_size(VALUE obj, VALUE args, VALUE eobj)
1840 {
1841 VALUE n, size;
1842 long slice_size = NUM2LONG(RARRAY_AREF(args, 0));
1843 if (slice_size <= 0) rb_raise(rb_eArgError, "invalid slice size");
1844
1845 size = enum_size(obj, 0, 0);
1846 if (size == Qnil) return Qnil;
1847
1848 n = rb_funcall(size, '+', 1, LONG2NUM(slice_size-1));
1849 return rb_funcall(n, id_div, 1, LONG2FIX(slice_size));
1850 }
1851
1852 /*
1853 * call-seq:
1854 * enum.each_slice(n) { ... } -> nil
1855 * enum.each_slice(n) -> an_enumerator
1856 *
1857 * Iterates the given block for each slice of <n> elements. If no
1858 * block is given, returns an enumerator.
1859 *
1860 * (1..10).each_slice(3) { |a| p a }
1861 * # outputs below
1862 * [1, 2, 3]
1863 * [4, 5, 6]
1864 * [7, 8, 9]
1865 * [10]
1866 *
1867 */
1868 static VALUE
1869 enum_each_slice(VALUE obj, VALUE n)
1870 {
1871 long size = NUM2LONG(n);
1872 VALUE ary;
1873 NODE *memo;
1874
1875 if (size <= 0) rb_raise(rb_eArgError, "invalid slice size");
1876 RETURN_SIZED_ENUMERATOR(obj, 1, &n, enum_each_slice_size);
1877 ary = rb_ary_new2(size);
1878 memo = NEW_MEMO(ary, 0, size);
1879 rb_block_call(obj, id_each, 0, 0, each_slice_i, (VALUE)memo);
1880 ary = memo->u1.value;
1881 if (RARRAY_LEN(ary) > 0) rb_yield(ary);
1882
1883 return Qnil;
1884 }
1885
1886 static VALUE
1887 each_cons_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
1888 {
1889 NODE *memo = RNODE(args);
1890 VALUE ary = memo->u1.value;
1891 VALUE v = Qnil;
1892 long size = memo->u3.cnt;
1893 ENUM_WANT_SVALUE();
1894
1895 if (RARRAY_LEN(ary) == size) {
1896 rb_ary_shift(ary);
1897 }
1898 rb_ary_push(ary, i);
1899 if (RARRAY_LEN(ary) == size) {
1900 v = rb_yield(rb_ary_dup(ary));
1901 }
1902 return v;
1903 }
1904
1905 static VALUE
1906 enum_each_cons_size(VALUE obj, VALUE args, VALUE eobj)
1907 {
1908 VALUE n, size;
1909 long cons_size = NUM2LONG(RARRAY_AREF(args, 0));
1910 if (cons_size <= 0) rb_raise(rb_eArgError, "invalid size");
1911
1912 size = enum_size(obj, 0, 0);
1913 if (size == Qnil) return Qnil;
1914
1915 n = rb_funcall(size, '+', 1, LONG2NUM(1 - cons_size));
1916 return (rb_cmpint(rb_funcall(n, id_cmp, 1, LONG2FIX(0)), n, LONG2FIX(0)) == -1) ? LONG2FIX(0) : n;
1917 }
1918
1919 /*
1920 * call-seq:
1921 * enum.each_cons(n) { ... } -> nil
1922 * enum.each_cons(n) -> an_enumerator
1923 *
1924 * Iterates the given block for each array of consecutive <n>
1925 * elements. If no block is given, returns an enumerator.
1926 *
1927 * e.g.:
1928 * (1..10).each_cons(3) { |a| p a }
1929 * # outputs below
1930 * [1, 2, 3]
1931 * [2, 3, 4]
1932 * [3, 4, 5]
1933 * [4, 5, 6]
1934 * [5, 6, 7]
1935 * [6, 7, 8]
1936 * [7, 8, 9]
1937 * [8, 9, 10]
1938 *
1939 */
1940 static VALUE
1941 enum_each_cons(VALUE obj, VALUE n)
1942 {
1943 long size = NUM2LONG(n);
1944 NODE *memo;
1945
1946 if (size <= 0) rb_raise(rb_eArgError, "invalid size");
1947 RETURN_SIZED_ENUMERATOR(obj, 1, &n, enum_each_cons_size);
1948 memo = NEW_MEMO(rb_ary_new2(size), 0, size);
1949 rb_block_call(obj, id_each, 0, 0, each_cons_i, (VALUE)memo);
1950
1951 return Qnil;
1952 }
1953
1954 static VALUE
1955 each_with_object_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo))
1956 {
1957 ENUM_WANT_SVALUE();
1958 return rb_yield_values(2, i, memo);
1959 }
1960
1961 /*
1962 * call-seq:
1963 * enum.each_with_object(obj) { |(*args), memo_obj| ... } -> obj
1964 * enum.each_with_object(obj) -> an_enumerator
1965 *
1966 * Iterates the given block for each element with an arbitrary
1967 * object given, and returns the initially given object.
1968 *
1969 * If no block is given, returns an enumerator.
1970 *
1971 * evens = (1..10).each_with_object([]) { |i, a| a << i*2 }
1972 * #=> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
1973 *
1974 */
1975 static VALUE
1976 enum_each_with_object(VALUE obj, VALUE memo)
1977 {
1978 RETURN_SIZED_ENUMERATOR(obj, 1, &memo, enum_size);
1979
1980 rb_block_call(obj, id_each, 0, 0, each_with_object_i, memo);
1981
1982 return memo;
1983 }
1984
1985 static VALUE
1986 zip_ary(RB_BLOCK_CALL_FUNC_ARGLIST(val, memoval))
1987 {
1988 NODE *memo = (NODE *)memoval;
1989 volatile VALUE result = memo->u1.value;
1990 volatile VALUE args = memo->u2.value;
1991 long n = memo->u3.cnt++;
1992 volatile VALUE tmp;
1993 int i;
1994
1995 tmp = rb_ary_new2(RARRAY_LEN(args) + 1);
1996 rb_ary_store(tmp, 0, rb_enum_values_pack(argc, argv));
1997 for (i=0; i<RARRAY_LEN(args); i++) {
1998 VALUE e = RARRAY_AREF(args, i);
1999
2000 if (RARRAY_LEN(e) <= n) {
2001 rb_ary_push(tmp, Qnil);
2002 }
2003 else {
2004 rb_ary_push(tmp, RARRAY_AREF(e, n));
2005 }
2006 }
2007 if (NIL_P(result)) {
2008 rb_yield(tmp);
2009 }
2010 else {
2011 rb_ary_push(result, tmp);
2012 }
2013 return Qnil;
2014 }
2015
2016 static VALUE
2017 call_next(VALUE *v)
2018 {
2019 return v[0] = rb_funcall(v[1], id_next, 0, 0);
2020 }
2021
2022 static VALUE
2023 call_stop(VALUE *v)
2024 {
2025 return v[0] = Qundef;
2026 }
2027
2028 static VALUE
2029 zip_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, memoval))
2030 {
2031 NODE *memo = (NODE *)memoval;
2032 volatile VALUE result = memo->u1.value;
2033 volatile VALUE args = memo->u2.value;
2034 volatile VALUE tmp;
2035 int i;
2036
2037 tmp = rb_ary_new2(RARRAY_LEN(args) + 1);
2038 rb_ary_store(tmp, 0, rb_enum_values_pack(argc, argv));
2039 for (i=0; i<RARRAY_LEN(args); i++) {
2040 if (NIL_P(RARRAY_AREF(args, i))) {
2041 rb_ary_push(tmp, Qnil);
2042 }
2043 else {
2044 VALUE v[2];
2045
2046 v[1] = RARRAY_AREF(args, i);
2047 rb_rescue2(call_next, (VALUE)v, call_stop, (VALUE)v, rb_eStopIteration, (VALUE)0);
2048 if (v[0] == Qundef) {
2049 RARRAY_ASET(args, i, Qnil);
2050 v[0] = Qnil;
2051 }
2052 rb_ary_push(tmp, v[0]);
2053 }
2054 }
2055 if (NIL_P(result)) {
2056 rb_yield(tmp);
2057 }
2058 else {
2059 rb_ary_push(result, tmp);
2060 }
2061 return Qnil;
2062 }
2063
2064 /*
2065 * call-seq:
2066 * enum.zip(arg, ...) -> an_array_of_array
2067 * enum.zip(arg, ...) { |arr| block } -> nil
2068 *
2069 * Takes one element from <i>enum</i> and merges corresponding
2070 * elements from each <i>args</i>. This generates a sequence of
2071 * <em>n</em>-element arrays, where <em>n</em> is one more than the
2072 * count of arguments. The length of the resulting sequence will be
2073 * <code>enum#size</code>. If the size of any argument is less than
2074 * <code>enum#size</code>, <code>nil</code> values are supplied. If
2075 * a block is given, it is invoked for each output array, otherwise
2076 * an array of arrays is returned.
2077 *
2078 * a = [ 4, 5, 6 ]
2079 * b = [ 7, 8, 9 ]
2080 *
2081 * [1, 2, 3].zip(a, b) #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
2082 * [1, 2].zip(a, b) #=> [[1, 4, 7], [2, 5, 8]]
2083 * a.zip([1, 2], [8]) #=> [[4, 1, 8], [5, 2, nil], [6, nil, nil]]
2084 *
2085 */
2086
2087 static VALUE
2088 enum_zip(int argc, VALUE *argv, VALUE obj)
2089 {
2090 int i;
2091 ID conv;
2092 NODE *memo;
2093 VALUE result = Qnil;
2094 VALUE args = rb_ary_new4(argc, argv);
2095 int allary = TRUE;
2096
2097 argv = RARRAY_PTR(args);
2098 for (i=0; i<argc; i++) {
2099 VALUE ary = rb_check_array_type(argv[i]);
2100 if (NIL_P(ary)) {
2101 allary = FALSE;
2102 break;
2103 }
2104 argv[i] = ary;
2105 }
2106 if (!allary) {
2107 CONST_ID(conv, "to_enum");
2108 for (i=0; i<argc; i++) {
2109 if (!rb_respond_to(argv[i], id_each)) {
2110 rb_raise(rb_eTypeError, "wrong argument type %s (must respond to :each)",
2111 rb_obj_classname(argv[i]));
2112 }
2113 argv[i] = rb_funcall(argv[i], conv, 1, ID2SYM(id_each));
2114 }
2115 }
2116 if (!rb_block_given_p()) {
2117 result = rb_ary_new();
2118 }
2119 /* use NODE_DOT2 as memo(v, v, -) */
2120 memo = rb_node_newnode(NODE_DOT2, result, args, 0);
2121 rb_block_call(obj, id_each, 0, 0, allary ? zip_ary : zip_i, (VALUE)memo);
2122
2123 return result;
2124 }
2125
2126 static VALUE
2127 take_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
2128 {
2129 NODE *memo = RNODE(args);
2130 rb_ary_push(memo->u1.value, rb_enum_values_pack(argc, argv));
2131 if (--memo->u3.cnt == 0) rb_iter_break();
2132 return Qnil;
2133 }
2134
2135 /*
2136 * call-seq:
2137 * enum.take(n) -> array
2138 *
2139 * Returns first n elements from <i>enum</i>.
2140 *
2141 * a = [1, 2, 3, 4, 5, 0]
2142 * a.take(3) #=> [1, 2, 3]
2143 *
2144 */
2145
2146 static VALUE
2147 enum_take(VALUE obj, VALUE n)
2148 {
2149 NODE *memo;
2150 VALUE result;
2151 long len = NUM2LONG(n);
2152
2153 if (len < 0) {
2154 rb_raise(rb_eArgError, "attempt to take negative size");
2155 }
2156
2157 if (len == 0) return rb_ary_new2(0);
2158 result = rb_ary_new2(len);
2159 memo = NEW_MEMO(result, 0, len);
2160 rb_block_call(obj, id_each, 0, 0, take_i, (VALUE)memo);
2161 return result;
2162 }
2163
2164
2165 static VALUE
2166 take_while_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
2167 {
2168 if (!RTEST(enum_yield(argc, argv))) rb_iter_break();
2169 rb_ary_push(ary, rb_enum_values_pack(argc, argv));
2170 return Qnil;
2171 }
2172
2173 /*
2174 * call-seq:
2175 * enum.take_while { |arr| block } -> array
2176 * enum.take_while -> an_enumerator
2177 *
2178 * Passes elements to the block until the block returns +nil+ or +false+,
2179 * then stops iterating and returns an array of all prior elements.
2180 *
2181 * If no block is given, an enumerator is returned instead.
2182 *
2183 * a = [1, 2, 3, 4, 5, 0]
2184 * a.take_while { |i| i < 3 } #=> [1, 2]
2185 *
2186 */
2187
2188 static VALUE
2189 enum_take_while(VALUE obj)
2190 {
2191 VALUE ary;
2192
2193 RETURN_ENUMERATOR(obj, 0, 0);
2194 ary = rb_ary_new();
2195 rb_block_call(obj, id_each, 0, 0, take_while_i, ary);
2196 return ary;
2197 }
2198
2199 static VALUE
2200 drop_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
2201 {
2202 NODE *memo = RNODE(args);
2203 if (memo->u3.cnt == 0) {
2204 rb_ary_push(memo->u1.value, rb_enum_values_pack(argc, argv));
2205 }
2206 else {
2207 memo->u3.cnt--;
2208 }
2209 return Qnil;
2210 }
2211
2212 /*
2213 * call-seq:
2214 * enum.drop(n) -> array
2215 *
2216 * Drops first n elements from <i>enum</i>, and returns rest elements
2217 * in an array.
2218 *
2219 * a = [1, 2, 3, 4, 5, 0]
2220 * a.drop(3) #=> [4, 5, 0]
2221 *
2222 */
2223
2224 static VALUE
2225 enum_drop(VALUE obj, VALUE n)
2226 {
2227 VALUE result;
2228 NODE *memo;
2229 long len = NUM2LONG(n);
2230
2231 if (len < 0) {
2232 rb_raise(rb_eArgError, "attempt to drop negative size");
2233 }
2234
2235 result = rb_ary_new();
2236 memo = NEW_MEMO(result, 0, len);
2237 rb_block_call(obj, id_each, 0, 0, drop_i, (VALUE)memo);
2238 return result;
2239 }
2240
2241
2242 static VALUE
2243 drop_while_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
2244 {
2245 NODE *memo = RNODE(args);
2246 ENUM_WANT_SVALUE();
2247
2248 if (!memo->u3.state && !RTEST(rb_yield(i))) {
2249 memo->u3.state = TRUE;
2250 }
2251 if (memo->u3.state) {
2252 rb_ary_push(memo->u1.value, i);
2253 }
2254 return Qnil;
2255 }
2256
2257 /*
2258 * call-seq:
2259 * enum.drop_while { |arr| block } -> array
2260 * enum.drop_while -> an_enumerator
2261 *
2262 * Drops elements up to, but not including, the first element for
2263 * which the block returns +nil+ or +false+ and returns an array
2264 * containing the remaining elements.
2265 *
2266 * If no block is given, an enumerator is returned instead.
2267 *
2268 * a = [1, 2, 3, 4, 5, 0]
2269 * a.drop_while { |i| i < 3 } #=> [3, 4, 5, 0]
2270 *
2271 */
2272
2273 static VALUE
2274 enum_drop_while(VALUE obj)
2275 {
2276 VALUE result;
2277 NODE *memo;
2278
2279 RETURN_ENUMERATOR(obj, 0, 0);
2280 result = rb_ary_new();
2281 memo = NEW_MEMO(result, 0, FALSE);
2282 rb_block_call(obj, id_each, 0, 0, drop_while_i, (VALUE)memo);
2283 return result;
2284 }
2285
2286 static VALUE
2287 cycle_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
2288 {
2289 ENUM_WANT_SVALUE();
2290
2291 rb_ary_push(ary, i);
2292 rb_yield(i);
2293 return Qnil;
2294 }
2295
2296 static VALUE
2297 enum_cycle_size(VALUE self, VALUE args, VALUE eobj)
2298 {
2299 long mul;
2300 VALUE n = Qnil;
2301 VALUE size = enum_size(self, args, 0);
2302
2303 if (size == Qnil) return Qnil;
2304
2305 if (args && (RARRAY_LEN(args) > 0)) {
2306 n = RARRAY_AREF(args, 0);
2307 }
2308 if (n == Qnil) return DBL2NUM(INFINITY);
2309 mul = NUM2LONG(n);
2310 if (mul <= 0) return INT2FIX(0);
2311 return rb_funcall(size, '*', 1, LONG2FIX(mul));
2312 }
2313
2314 /*
2315 * call-seq:
2316 * enum.cycle(n=nil) { |obj| block } -> nil
2317 * enum.cycle(n=nil) -> an_enumerator
2318 *
2319 * Calls <i>block</i> for each element of <i>enum</i> repeatedly _n_
2320 * times or forever if none or +nil+ is given. If a non-positive
2321 * number is given or the collection is empty, does nothing. Returns
2322 * +nil+ if the loop has finished without getting interrupted.
2323 *
2324 * Enumerable#cycle saves elements in an internal array so changes
2325 * to <i>enum</i> after the first pass have no effect.
2326 *
2327 * If no block is given, an enumerator is returned instead.
2328 *
2329 * a = ["a", "b", "c"]
2330 * a.cycle { |x| puts x } # print, a, b, c, a, b, c,.. forever.
2331 * a.cycle(2) { |x| puts x } # print, a, b, c, a, b, c.
2332 *
2333 */
2334
2335 static VALUE
2336 enum_cycle(int argc, VALUE *argv, VALUE obj)
2337 {
2338 VALUE ary;
2339 VALUE nv = Qnil;
2340 long n, i, len;
2341
2342 rb_scan_args(argc, argv, "01", &nv);
2343
2344 RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_cycle_size);
2345 if (NIL_P(nv)) {
2346 n = -1;
2347 }
2348 else {
2349 n = NUM2LONG(nv);
2350 if (n <= 0) return Qnil;
2351 }
2352 ary = rb_ary_new();
2353 RBASIC_CLEAR_CLASS(ary);
2354 rb_block_call(obj, id_each, 0, 0, cycle_i, ary);
2355 len = RARRAY_LEN(ary);
2356 if (len == 0) return Qnil;
2357 while (n < 0 || 0 < --n) {
2358 for (i=0; i<len; i++) {
2359 rb_yield(RARRAY_AREF(ary, i));
2360 }
2361 }
2362 return Qnil;
2363 }
2364
2365 struct chunk_arg {
2366 VALUE categorize;
2367 VALUE state;
2368 VALUE prev_value;
2369 VALUE prev_elts;
2370 VALUE yielder;
2371 };
2372
2373 static VALUE
2374 chunk_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, _argp))
2375 {
2376 struct chunk_arg *argp = MEMO_FOR(struct chunk_arg, _argp);
2377 VALUE v;
2378 VALUE alone = ID2SYM(rb_intern("_alone"));
2379 VALUE separator = ID2SYM(rb_intern("_separator"));
2380
2381 ENUM_WANT_SVALUE();
2382
2383 if (NIL_P(argp->state))
2384 v = rb_funcall(argp->categorize, id_call, 1, i);
2385 else
2386 v = rb_funcall(argp->categorize, id_call, 2, i, argp->state);
2387
2388 if (v == alone) {
2389 if (!NIL_P(argp->prev_value)) {
2390 rb_funcall(argp->yielder, id_lshift, 1, rb_assoc_new(argp->prev_value, argp->prev_elts));
2391 argp->prev_value = argp->prev_elts = Qnil;
2392 }
2393 rb_funcall(argp->yielder, id_lshift, 1, rb_assoc_new(v, rb_ary_new3(1, i)));
2394 }
2395 else if (NIL_P(v) || v == separator) {
2396 if (!NIL_P(argp->prev_value)) {
2397 rb_funcall(argp->yielder, id_lshift, 1, rb_assoc_new(argp->prev_value, argp->prev_elts));
2398 argp->prev_value = argp->prev_elts = Qnil;
2399 }
2400 }
2401 else if (SYMBOL_P(v) && rb_id2name(SYM2ID(v))[0] == '_') {
2402 rb_raise(rb_eRuntimeError, "symbols beginning with an underscore are reserved");
2403 }
2404 else {
2405 if (NIL_P(argp->prev_value)) {
2406 argp->prev_value = v;
2407 argp->prev_elts = rb_ary_new3(1, i);
2408 }
2409 else {
2410 if (rb_equal(argp->prev_value, v)) {
2411 rb_ary_push(argp->prev_elts, i);
2412 }
2413 else {
2414 rb_funcall(argp->yielder, id_lshift, 1, rb_assoc_new(argp->prev_value, argp->prev_elts));
2415 argp->prev_value = v;
2416 argp->prev_elts = rb_ary_new3(1, i);
2417 }
2418 }
2419 }
2420 return Qnil;
2421 }
2422
2423 static VALUE
2424 chunk_i(RB_BLOCK_CALL_FUNC_ARGLIST(yielder, enumerator))
2425 {
2426 VALUE enumerable;
2427 VALUE arg;
2428 struct chunk_arg *memo = NEW_MEMO_FOR(struct chunk_arg, arg);
2429
2430 enumerable = rb_ivar_get(enumerator, rb_intern("chunk_enumerable"));
2431 memo->categorize = rb_ivar_get(enumerator, rb_intern("chunk_categorize"));
2432 memo->state = rb_ivar_get(enumerator, rb_intern("chunk_initial_state"));
2433 memo->prev_value = Qnil;
2434 memo->prev_elts = Qnil;
2435 memo->yielder = yielder;
2436
2437 if (!NIL_P(memo->state))
2438 memo->state = rb_obj_dup(memo->state);
2439
2440 rb_block_call(enumerable, id_each, 0, 0, chunk_ii, arg);
2441 memo = MEMO_FOR(struct chunk_arg, arg);
2442 if (!NIL_P(memo->prev_elts))
2443 rb_funcall(memo->yielder, id_lshift, 1, rb_assoc_new(memo->prev_value, memo->prev_elts));
2444 return Qnil;
2445 }
2446
2447 /*
2448 * call-seq:
2449 * enum.chunk { |elt| ... } -> an_enumerator
2450 * enum.chunk(initial_state) { |elt, state| ... } -> an_enumerator
2451 *
2452 * Enumerates over the items, chunking them together based on the return
2453 * value of the block.
2454 *
2455 * Consecutive elements which return the same block value are chunked together.
2456 *
2457 * For example, consecutive even numbers and odd numbers can be
2458 * chunked as follows.
2459 *
2460 * [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5].chunk { |n|
2461 * n.even?
2462 * }.each { |even, ary|
2463 * p [even, ary]
2464 * }
2465 * #=> [false, [3, 1]]
2466 * # [true, [4]]
2467 * # [false, [1, 5, 9]]
2468 * # [true, [2, 6]]
2469 * # [false, [5, 3, 5]]
2470 *
2471 * This method is especially useful for sorted series of elements.
2472 * The following example counts words for each initial letter.
2473 *
2474 * open("/usr/share/dict/words", "r:iso-8859-1") { |f|
2475 * f.chunk { |line| line.ord }.each { |ch, lines| p [ch.chr, lines.length] }
2476 * }
2477 * #=> ["\n", 1]
2478 * # ["A", 1327]
2479 * # ["B", 1372]
2480 * # ["C", 1507]
2481 * # ["D", 791]
2482 * # ...
2483 *
2484 * The following key values have special meaning:
2485 * - +nil+ and +:_separator+ specifies that the elements should be dropped.
2486 * - +:_alone+ specifies that the element should be chunked by itself.
2487 *
2488 * Any other symbols that begin with an underscore will raise an error:
2489 *
2490 * items.chunk { |item| :_underscore }
2491 * #=> RuntimeError: symbols beginning with an underscore are reserved
2492 *
2493 * +nil+ and +:_separator+ can be used to ignore some elements.
2494 *
2495 * For example, the sequence of hyphens in svn log can be eliminated as follows:
2496 *
2497 * sep = "-"*72 + "\n"
2498 * IO.popen("svn log README") { |f|
2499 * f.chunk { |line|
2500 * line != sep || nil
2501 * }.each { |_, lines|
2502 * pp lines
2503 * }
2504 * }
2505 * #=> ["r20018 | knu | 2008-10-29 13:20:42 +0900 (Wed, 29 Oct 2008) | 2 lines\n",
2506 * # "\n",
2507 * # "* README, README.ja: Update the portability section.\n",
2508 * # "\n"]
2509 * # ["r16725 | knu | 2008-05-31 23:34:23 +0900 (Sat, 31 May 2008) | 2 lines\n",
2510 * # "\n",
2511 * # "* README, README.ja: Add a note about default C flags.\n",
2512 * # "\n"]
2513 * # ...
2514 *
2515 * Paragraphs separated by empty lines can be parsed as follows:
2516 *
2517 * File.foreach("README").chunk { |line|
2518 * /\A\s*\z/ !~ line || nil
2519 * }.each { |_, lines|
2520 * pp lines
2521 * }
2522 *
2523 * +:_alone+ can be used to force items into their own chunk.
2524 * For example, you can put lines that contain a URL by themselves,
2525 * and chunk the rest of the lines together, like this:
2526 *
2527 * pattern = /http/
2528 * open(filename) { |f|
2529 * f.chunk { |line| line =~ pattern ? :_alone : true }.each { |key, lines|
2530 * pp lines
2531 * }
2532 * }
2533 *
2534 * If the block needs to maintain state over multiple elements,
2535 * an +initial_state+ argument can be used.
2536 * If a non-nil value is given,
2537 * a reference to it is passed as the 2nd argument of the block for the
2538 * +chunk+ method, so state-changes to it persist across block calls.
2539 *
2540 */
2541 static VALUE
2542 enum_chunk(int argc, VALUE *argv, VALUE enumerable)
2543 {
2544 VALUE initial_state;
2545 VALUE enumerator;
2546
2547 if (!rb_block_given_p())
2548 rb_raise(rb_eArgError, "no block given");
2549 rb_scan_args(argc, argv, "01", &initial_state);
2550
2551 enumerator = rb_obj_alloc(rb_cEnumerator);
2552 rb_ivar_set(enumerator, rb_intern("chunk_enumerable"), enumerable);
2553 rb_ivar_set(enumerator, rb_intern("chunk_categorize"), rb_block_proc());
2554 rb_ivar_set(enumerator, rb_intern("chunk_initial_state"), initial_state);
2555 rb_block_call(enumerator, idInitialize, 0, 0, chunk_i, enumerator);
2556 return enumerator;
2557 }
2558
2559
2560 struct slicebefore_arg {
2561 VALUE sep_pred;
2562 VALUE sep_pat;
2563 VALUE state;
2564 VALUE prev_elts;
2565 VALUE yielder;
2566 };
2567
2568 static VALUE
2569 slicebefore_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, _argp))
2570 {
2571 struct slicebefore_arg *argp = MEMO_FOR(struct slicebefore_arg, _argp);
2572 VALUE header_p;
2573
2574 ENUM_WANT_SVALUE();
2575
2576 if (!NIL_P(argp->sep_pat))
2577 header_p = rb_funcall(argp->sep_pat, id_eqq, 1, i);
2578 else if (NIL_P(argp->state))
2579 header_p = rb_funcall(argp->sep_pred, id_call, 1, i);
2580 else
2581 header_p = rb_funcall(argp->sep_pred, id_call, 2, i, argp->state);
2582 if (RTEST(header_p)) {
2583 if (!NIL_P(argp->prev_elts))
2584 rb_funcall(argp->yielder, id_lshift, 1, argp->prev_elts);
2585 argp->prev_elts = rb_ary_new3(1, i);
2586 }
2587 else {
2588 if (NIL_P(argp->prev_elts))
2589 argp->prev_elts = rb_ary_new3(1, i);
2590 else
2591 rb_ary_push(argp->prev_elts, i);
2592 }
2593
2594 return Qnil;
2595 }
2596
2597 static VALUE
2598 slicebefore_i(RB_BLOCK_CALL_FUNC_ARGLIST(yielder, enumerator))
2599 {
2600 VALUE enumerable;
2601 VALUE arg;
2602 struct slicebefore_arg *memo = NEW_MEMO_FOR(struct slicebefore_arg, arg);
2603
2604 enumerable = rb_ivar_get(enumerator, rb_intern("slicebefore_enumerable"));
2605 memo->sep_pred = rb_attr_get(enumerator, rb_intern("slicebefore_sep_pred"));
2606 memo->sep_pat = NIL_P(memo->sep_pred) ? rb_ivar_get(enumerator, rb_intern("slicebefore_sep_pat")) : Qnil;
2607 memo->state = rb_attr_get(enumerator, rb_intern("slicebefore_initial_state"));
2608 memo->prev_elts = Qnil;
2609 memo->yielder = yielder;
2610
2611 if (!NIL_P(memo->state))
2612 memo->state = rb_obj_dup(memo->state);
2613
2614 rb_block_call(enumerable, id_each, 0, 0, slicebefore_ii, arg);
2615 memo = MEMO_FOR(struct slicebefore_arg, arg);
2616 if (!NIL_P(memo->prev_elts))
2617 rb_funcall(memo->yielder, id_lshift, 1, memo->prev_elts);
2618 return Qnil;
2619 }
2620
2621 /*
2622 * call-seq:
2623 * enum.slice_before(pattern) -> an_enumerator
2624 * enum.slice_before { |elt| bool } -> an_enumerator
2625 * enum.slice_before(initial_state) { |elt, state| bool } -> an_enumerator
2626 *
2627 * Creates an enumerator for each chunked elements.
2628 * The beginnings of chunks are defined by _pattern_ and the block.
2629
2630 * If <code>_pattern_ === _elt_</code> returns <code>true</code> or the block
2631 * returns <code>true</code> for the element, the element is beginning of a
2632 * chunk.
2633
2634 * The <code>===</code> and _block_ is called from the first element to the last
2635 * element of _enum_. The result for the first element is ignored.
2636
2637 * The result enumerator yields the chunked elements as an array.
2638 * So +each+ method can be called as follows:
2639 *
2640 * enum.slice_before(pattern).each { |ary| ... }
2641 * enum.slice_before { |elt| bool }.each { |ary| ... }
2642 * enum.slice_before(initial_state) { |elt, state| bool }.each { |ary| ... }
2643 *
2644 * Other methods of the Enumerator class and Enumerable module,
2645 * such as map, etc., are also usable.
2646 *
2647 * For example, iteration over ChangeLog entries can be implemented as
2648 * follows:
2649 *
2650 * # iterate over ChangeLog entries.
2651 * open("ChangeLog") { |f|
2652 * f.slice_before(/\A\S/).each { |e| pp e }
2653 * }
2654 *
2655 * # same as above. block is used instead of pattern argument.
2656 * open("ChangeLog") { |f|
2657 * f.slice_before { |line| /\A\S/ === line }.each { |e| pp e }
2658 * }
2659 *
2660 *
2661 * "svn proplist -R" produces multiline output for each file.
2662 * They can be chunked as follows:
2663 *
2664 * IO.popen([{"LC_ALL"=>"C"}, "svn", "proplist", "-R"]) { |f|
2665 * f.lines.slice_before(/\AProp/).each { |lines| p lines }
2666 * }
2667 * #=> ["Properties on '.':\n", " svn:ignore\n", " svk:merge\n"]
2668 * # ["Properties on 'goruby.c':\n", " svn:eol-style\n"]
2669 * # ["Properties on 'complex.c':\n", " svn:mime-type\n", " svn:eol-style\n"]
2670 * # ["Properties on 'regparse.c':\n", " svn:eol-style\n"]
2671 * # ...
2672 *
2673 * If the block needs to maintain state over multiple elements,
2674 * local variables can be used.
2675 * For example, three or more consecutive increasing numbers can be squashed
2676 * as follows:
2677 *
2678 * a = [0, 2, 3, 4, 6, 7, 9]
2679 * prev = a[0]
2680 * p a.slice_before { |e|
2681 * prev, prev2 = e, prev
2682 * prev2 + 1 != e
2683 * }.map { |es|
2684 * es.length <= 2 ? es.join(",") : "#{es.first}-#{es.last}"
2685 * }.join(",")
2686 * #=> "0,2-4,6,7,9"
2687 *
2688 * However local variables are not appropriate to maintain state
2689 * if the result enumerator is used twice or more.
2690 * In such a case, the last state of the 1st +each+ is used in the 2nd +each+.
2691 * The _initial_state_ argument can be used to avoid this problem.
2692 * If non-nil value is given as _initial_state_,
2693 * it is duplicated for each +each+ method invocation of the enumerator.
2694 * The duplicated object is passed to 2nd argument of the block for
2695 * +slice_before+ method.
2696 *
2697 * # Word wrapping. This assumes all characters have same width.
2698 * def wordwrap(words, maxwidth)
2699 * # if cols is a local variable, 2nd "each" may start with non-zero cols.
2700 * words.slice_before(cols: 0) { |w, h|
2701 * h[:cols] += 1 if h[:cols] != 0
2702 * h[:cols] += w.length
2703 * if maxwidth < h[:cols]
2704 * h[:cols] = w.length
2705 * true
2706 * else
2707 * false
2708 * end
2709 * }
2710 * end
2711 * text = (1..20).to_a.join(" ")
2712 * enum = wordwrap(text.split(/\s+/), 10)
2713 * puts "-"*10
2714 * enum.each { |ws| puts ws.join(" ") }
2715 * puts "-"*10
2716 * #=> ----------
2717 * # 1 2 3 4 5
2718 * # 6 7 8 9 10
2719 * # 11 12 13
2720 * # 14 15 16
2721 * # 17 18 19
2722 * # 20
2723 * # ----------
2724 *
2725 * mbox contains series of mails which start with Unix From line.
2726 * So each mail can be extracted by slice before Unix From line.
2727 *
2728 * # parse mbox
2729 * open("mbox") { |f|
2730 * f.slice_before { |line|
2731 * line.start_with? "From "
2732 * }.each { |mail|
2733 * unix_from = mail.shift
2734 * i = mail.index("\n")
2735 * header = mail[0...i]
2736 * body = mail[(i+1)..-1]
2737 * body.pop if body.last == "\n"
2738 * fields = header.slice_before { |line| !" \t".include?(line[0]) }.to_a
2739 * p unix_from
2740 * pp fields
2741 * pp body
2742 * }
2743 * }
2744 *
2745 * # split mails in mbox (slice before Unix From line after an empty line)
2746 * open("mbox") { |f|
2747 * f.slice_before(emp: true) { |line, h|
2748 * prevemp = h[:emp]
2749 * h[:emp] = line == "\n"
2750 * prevemp && line.start_with?("From ")
2751 * }.each { |mail|
2752 * mail.pop if mail.last == "\n"
2753 * pp mail
2754 * }
2755 * }
2756 *
2757 */
2758 static VALUE
2759 enum_slice_before(int argc, VALUE *argv, VALUE enumerable)
2760 {
2761 VALUE enumerator;
2762
2763 if (rb_block_given_p()) {
2764 VALUE initial_state;
2765 rb_scan_args(argc, argv, "01", &initial_state);
2766 enumerator = rb_obj_alloc(rb_cEnumerator);
2767 rb_ivar_set(enumerator, rb_intern("slicebefore_sep_pred"), rb_block_proc());
2768 rb_ivar_set(enumerator, rb_intern("slicebefore_initial_state"), initial_state);
2769 }
2770 else {
2771 VALUE sep_pat;
2772 rb_scan_args(argc, argv, "1", &sep_pat);
2773 enumerator = rb_obj_alloc(rb_cEnumerator);
2774 rb_ivar_set(enumerator, rb_intern("slicebefore_sep_pat"), sep_pat);
2775 }
2776 rb_ivar_set(enumerator, rb_intern("slicebefore_enumerable"), enumerable);
2777 rb_block_call(enumerator, idInitialize, 0, 0, slicebefore_i, enumerator);
2778 return enumerator;
2779 }
2780
2781 /*
2782 * The <code>Enumerable</code> mixin provides collection classes with
2783 * several traversal and searching methods, and with the ability to
2784 * sort. The class must provide a method <code>each</code>, which
2785 * yields successive members of the collection. If
2786 * <code>Enumerable#max</code>, <code>#min</code>, or
2787 * <code>#sort</code> is used, the objects in the collection must also
2788 * implement a meaningful <code><=></code> operator, as these methods
2789 * rely on an ordering between members of the collection.
2790 */
2791
2792 void
2793 Init_Enumerable(void)
2794 {
2795 #undef rb_intern
2796 #define rb_intern(str) rb_intern_const(str)
2797
2798 rb_mEnumerable = rb_define_module("Enumerable");
2799
2800 rb_define_method(rb_mEnumerable, "to_a", enum_to_a, -1);
2801 rb_define_method(rb_mEnumerable, "entries", enum_to_a, -1);
2802 rb_define_method(rb_mEnumerable, "to_h", enum_to_h, -1);
2803
2804 rb_define_method(rb_mEnumerable, "sort", enum_sort, 0);
2805 rb_define_method(rb_mEnumerable, "sort_by", enum_sort_by, 0);
2806 rb_define_method(rb_mEnumerable, "grep", enum_grep, 1);
2807 rb_define_method(rb_mEnumerable, "count", enum_count, -1);
2808 rb_define_method(rb_mEnumerable, "find", enum_find, -1);
2809 rb_define_method(rb_mEnumerable, "detect", enum_find, -1);
2810 rb_define_method(rb_mEnumerable, "find_index", enum_find_index, -1);
2811 rb_define_method(rb_mEnumerable, "find_all", enum_find_all, 0);
2812 rb_define_method(rb_mEnumerable, "select", enum_find_all, 0);
2813 rb_define_method(rb_mEnumerable, "reject", enum_reject, 0);
2814 rb_define_method(rb_mEnumerable, "collect", enum_collect, 0);
2815 rb_define_method(rb_mEnumerable, "map", enum_collect, 0);
2816 rb_define_method(rb_mEnumerable, "flat_map", enum_flat_map, 0);
2817 rb_define_method(rb_mEnumerable, "collect_concat", enum_flat_map, 0);
2818 rb_define_method(rb_mEnumerable, "inject", enum_inject, -1);
2819 rb_define_method(rb_mEnumerable, "reduce", enum_inject, -1);
2820 rb_define_method(rb_mEnumerable, "partition", enum_partition, 0);
2821 rb_define_method(rb_mEnumerable, "group_by", enum_group_by, 0);
2822 rb_define_method(rb_mEnumerable, "first", enum_first, -1);
2823 rb_define_method(rb_mEnumerable, "all?", enum_all, 0);
2824 rb_define_method(rb_mEnumerable, "any?", enum_any, 0);
2825 rb_define_method(rb_mEnumerable, "one?", enum_one, 0);
2826 rb_define_method(rb_mEnumerable, "none?", enum_none, 0);
2827 rb_define_method(rb_mEnumerable, "min", enum_min, 0);
2828 rb_define_method(rb_mEnumerable, "max", enum_max, 0);
2829 rb_define_method(rb_mEnumerable, "minmax", enum_minmax, 0);
2830 rb_define_method(rb_mEnumerable, "min_by", enum_min_by, 0);
2831 rb_define_method(rb_mEnumerable, "max_by", enum_max_by, 0);
2832 rb_define_method(rb_mEnumerable, "minmax_by", enum_minmax_by, 0);
2833 rb_define_method(rb_mEnumerable, "member?", enum_member, 1);
2834 rb_define_method(rb_mEnumerable, "include?", enum_member, 1);
2835 rb_define_method(rb_mEnumerable, "each_with_index", enum_each_with_index, -1);
2836 rb_define_method(rb_mEnumerable, "reverse_each", enum_reverse_each, -1);
2837 rb_define_method(rb_mEnumerable, "each_entry", enum_each_entry, -1);
2838 rb_define_method(rb_mEnumerable, "each_slice", enum_each_slice, 1);
2839 rb_define_method(rb_mEnumerable, "each_cons", enum_each_cons, 1);
2840 rb_define_method(rb_mEnumerable, "each_with_object", enum_each_with_object, 1);
2841 rb_define_method(rb_mEnumerable, "zip", enum_zip, -1);
2842 rb_define_method(rb_mEnumerable, "take", enum_take, 1);
2843 rb_define_method(rb_mEnumerable, "take_while", enum_take_while, 0);
2844 rb_define_method(rb_mEnumerable, "drop", enum_drop, 1);
2845 rb_define_method(rb_mEnumerable, "drop_while", enum_drop_while, 0);
2846 rb_define_method(rb_mEnumerable, "cycle", enum_cycle, -1);
2847 rb_define_method(rb_mEnumerable, "chunk", enum_chunk, -1);
2848 rb_define_method(rb_mEnumerable, "slice_before", enum_slice_before, -1);
2849
2850 id_next = rb_intern("next");
2851 id_call = rb_intern("call");
2852 id_size = rb_intern("size");
2853 id_div = rb_intern("div");
2854 }
id_lshift
#define id_lshift
Definition: enum.c:30
RBASIC_CLEAR_CLASS
#define RBASIC_CLEAR_CLASS(obj)
Definition: internal.h:607
rb_builtin_class_name
const char * rb_builtin_class_name(VALUE x)
Definition: error.c:451
NODE_DOT2
Definition: node.h:197
enum_any
static VALUE enum_any(VALUE obj)
Definition: enum.c:1087
grep_i
static VALUE grep_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
Definition: enum.c:47
RARRAY_LEN
#define RARRAY_LEN(a)
Definition: ruby.h:878
rb_intern
#define rb_intern(str)
enum_all
static VALUE enum_all(VALUE obj)
Definition: enum.c:1053
FALSE
#define FALSE
Definition: nkf.h:174
NEW_MEMO_FOR
#define NEW_MEMO_FOR(type, value)
Definition: node.h:470
slicebefore_i
static VALUE slicebefore_i(RB_BLOCK_CALL_FUNC_ARGLIST(yielder, enumerator))
Definition: enum.c:2598
id_each
#define id_each
Definition: enum.c:27
INT2NUM
#define INT2NUM(x)
Definition: ruby.h:1288
enumerator
Definition: enumerator.c:113
minmax_i
static VALUE minmax_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo))
Definition: enum.c:1343
chunk_arg::state
VALUE state
Definition: enum.c:2367
enum_each_with_index
static VALUE enum_each_with_index(int argc, VALUE *argv, VALUE obj)
Definition: enum.c:1726
rb_yield_values
VALUE rb_yield_values(int n,...)
Definition: vm_eval.c:953
sort_by_cmp
static int sort_by_cmp(const void *ap, const void *bp, void *data)
Definition: enum.c:869
node.h
ruby.h
rb_ary_sort
VALUE rb_ary_sort(VALUE ary)
Definition: array.c:2507
MEMO_FOR
#define MEMO_FOR(type, value)
Definition: node.h:469
count_all_i
static VALUE count_all_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
Definition: enum.c:124
Qtrue
#define Qtrue
Definition: ruby.h:426
slicebefore_ii
static VALUE slicebefore_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, _argp))
Definition: enum.c:2569
each_with_object_i
static VALUE each_with_object_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo))
Definition: enum.c:1955
min_by_i
static VALUE min_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
Definition: enum.c:1467
rb_ary_shift
VALUE rb_ary_shift(VALUE ary)
Definition: array.c:991
count_iter_i
static VALUE count_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
Definition: enum.c:113
id
const int id
Definition: nkf.c:209
enum_each_slice
static VALUE enum_each_slice(VALUE obj, VALUE n)
Definition: enum.c:1869
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:548
rb_check_arity
#define rb_check_arity
Definition: intern.h:296
slicebefore_arg::state
VALUE state
Definition: enum.c:2563
UNREACHABLE
#define UNREACHABLE
Definition: ruby.h:42
slicebefore_arg::sep_pred
VALUE sep_pred
Definition: enum.c:2561
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:896
SYM2ID
#define SYM2ID(x)
Definition: ruby.h:356
enum_each_cons
static VALUE enum_each_cons(VALUE obj, VALUE n)
Definition: enum.c:1941
slicebefore_arg::yielder
VALUE yielder
Definition: enum.c:2565
rb_ary_tmp_new
VALUE rb_ary_tmp_new(long capa)
Definition: array.c:534
enum_sort_by
static VALUE enum_sort_by(VALUE obj)
Definition: enum.c:957
rb_funcall
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:775
enum_member
static VALUE enum_member(VALUE obj, VALUE val)
Definition: enum.c:1690
rb_cEnumerator
VALUE rb_cEnumerator
Definition: enumerator.c:105
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1857
rb_ivar_get
VALUE rb_ivar_get(VALUE, ID)
Definition: variable.c:1115
DEFINE_ENUMFUNCS
#define DEFINE_ENUMFUNCS(name)
Definition: enum.c:1008
enum_slice_before
static VALUE enum_slice_before(int argc, VALUE *argv, VALUE enumerable)
Definition: enum.c:2759
sort_by_i
static VALUE sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, _data))
Definition: enum.c:841
rb_block_call
VALUE rb_block_call(VALUE, ID, int, const VALUE *, rb_block_call_func_t, VALUE)
T_ARRAY
#define T_ARRAY
Definition: ruby.h:484
minmax_by_t::max
VALUE max
Definition: enum.c:1562
minmax_t::max
VALUE max
Definition: enum.c:1315
RNode::argc
long argc
Definition: node.h:252
chunk_arg::yielder
VALUE yielder
Definition: enum.c:2370
rb_check_id
ID rb_check_id(volatile VALUE *namep)
Returns ID for the given name if it is interned already, or 0.
Definition: ripper.c:17324
sort_by_data
Definition: enum.c:834
minmax_t::last
VALUE last
Definition: enum.c:1316
rb_cmpint
int rb_cmpint(VALUE val, VALUE a, VALUE b)
Definition: bignum.c:2909
enum_to_h
static VALUE enum_to_h(int argc, VALUE *argv, VALUE obj)
Definition: enum.c:543
RNode::u3
union RNode::@131 u3
rb_f_send
VALUE rb_f_send(int argc, VALUE *argv, VALUE recv)
Definition: vm_eval.c:908
rb_obj_classname
const char * rb_obj_classname(VALUE)
Definition: variable.c:406
rb_ary_new2
#define rb_ary_new2
Definition: intern.h:90
id.h
RNode
Definition: node.h:239
Init_Enumerable
void Init_Enumerable(void)
Definition: enum.c:2793
find_i
static VALUE find_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
Definition: enum.c:179
RB_BLOCK_CALL_FUNC_ARGLIST
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
Definition: ruby.h:1511
ENUM_WANT_SVALUE
#define ENUM_WANT_SVALUE()
Definition: enum.c:40
group_by_i
static VALUE group_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash))
Definition: enum.c:716
rb_obj_dup
VALUE rb_obj_dup(VALUE)
Definition: object.c:406
chunk_arg::prev_value
VALUE prev_value
Definition: enum.c:2368
RBASIC_SET_CLASS_RAW
#define RBASIC_SET_CLASS_RAW(obj, cls)
Definition: internal.h:608
RB_TYPE_P
#define RB_TYPE_P(obj, type)
Definition: ruby.h:1664
enum_max
static VALUE enum_max(VALUE obj)
Definition: enum.c:1297
enum_max_by
static VALUE enum_max_by(VALUE obj)
Definition: enum.c:1547
rb_block_call_func
VALUE rb_block_call_func(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg))
Definition: ruby.h:1513
each_with_index_i
static VALUE each_with_index_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo))
Definition: enum.c:1699
rb_iter_break
void rb_iter_break(void)
Definition: vm.c:1154
sort_by_data::n
long n
Definition: enum.c:837
id_size
static ID id_size
Definition: enum.c:25
enum_take
static VALUE enum_take(VALUE obj, VALUE n)
Definition: enum.c:2147
enum_chunk
static VALUE enum_chunk(int argc, VALUE *argv, VALUE enumerable)
Definition: enum.c:2542
flat_map_i
static VALUE flat_map_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
Definition: enum.c:442
rb_block_given_p
int rb_block_given_p(void)
Definition: eval.c:712
rb_hash_aset
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:1393
member_i
static VALUE member_i(RB_BLOCK_CALL_FUNC_ARGLIST(iter, args))
Definition: enum.c:1665
val
#define val
rb_eRuntimeError
VALUE rb_eRuntimeError
Definition: error.c:547
enum_sort
static VALUE enum_sort(VALUE obj)
Definition: enum.c:828
RNode::u2
union RNode::@130 u2
enum_each_entry
static VALUE enum_each_entry(int argc, VALUE *argv, VALUE obj)
Definition: enum.c:1812
rb_ary_new
VALUE rb_ary_new(void)
Definition: array.c:495
enum_inject
static VALUE enum_inject(int argc, VALUE *argv, VALUE obj)
Definition: enum.c:636
UINT2NUM
#define UINT2NUM(x)
Definition: ruby.h:1298
enum_grep
static VALUE enum_grep(VALUE obj, VALUE pat)
Definition: enum.c:89
NIL_P
#define NIL_P(v)
Definition: ruby.h:438
enum_find_all
static VALUE enum_find_all(VALUE obj)
Definition: enum.c:341
enum_cycle_size
static VALUE enum_cycle_size(VALUE self, VALUE args, VALUE eobj)
Definition: enum.c:2297
SORT_BY_BUFSIZE
#define SORT_BY_BUFSIZE
Definition: enum.c:833
rb_ary_store
void rb_ary_store(VALUE ary, long idx, VALUE val)
Definition: array.c:790
RNode::value
VALUE value
Definition: node.h:245
offsetof
#define offsetof(p_type, field)
Definition: addrinfo.h:186
minmax_i_update
static void minmax_i_update(VALUE i, VALUE j, struct minmax_t *memo)
Definition: enum.c:1322
one
static double one(void)
Definition: isinf.c:52
RNode::u1
union RNode::@129 u1
argc
int argc
Definition: ruby.c:131
Qfalse
#define Qfalse
Definition: ruby.h:425
enum_first
static VALUE enum_first(int argc, VALUE *argv, VALUE obj)
Definition: enum.c:795
LONG_MAX
#define LONG_MAX
Definition: ruby.h:191
count_i
static VALUE count_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
Definition: enum.c:100
rb_ary_new4
#define rb_ary_new4
Definition: intern.h:92
rb_obj_alloc
VALUE rb_obj_alloc(VALUE)
Definition: object.c:1801
RNODE
#define RNODE(obj)
Definition: node.h:266
minmax_by_i_update
static void minmax_by_i_update(VALUE v1, VALUE v2, VALUE i1, VALUE i2, struct minmax_by_t *memo)
Definition: enum.c:1568
RNode::cnt
long cnt
Definition: node.h:261
chunk_ii
static VALUE chunk_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, _argp))
Definition: enum.c:2374
numberof
#define numberof(array)
Definition: etc.c:595
max_by_i
static VALUE max_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
Definition: enum.c:1513
enum_cycle
static VALUE enum_cycle(int argc, VALUE *argv, VALUE obj)
Definition: enum.c:2336
rb_yield
VALUE rb_yield(VALUE)
Definition: vm_eval.c:942
func
SSL_METHOD *(* func)(void)
Definition: ossl_ssl.c:113
util.h
TRUE
#define TRUE
Definition: nkf.h:175
rb_mEnumerable
VALUE rb_mEnumerable
Definition: enum.c:20
chunk_arg::categorize
VALUE categorize
Definition: enum.c:2366
RARRAY_PTR_USE
#define RARRAY_PTR_USE(ary, ptr_name, expr)
Definition: ruby.h:894
rb_node_newnode
#define rb_node_newnode(type, a1, a2, a3)
Definition: ripper.c:424
inject_op_i
static VALUE inject_op_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, p))
Definition: enum.c:569
rb_hash_new
VALUE rb_hash_new(void)
Definition: hash.c:298
slicebefore_arg
Definition: enum.c:2560
enum_each_cons_size
static VALUE enum_each_cons_size(VALUE obj, VALUE args, VALUE eobj)
Definition: enum.c:1906
rb_scan_args
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1728
min_ii
static VALUE min_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
Definition: enum.c:1191
rb_ivar_set
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1133
slicebefore_arg::sep_pat
VALUE sep_pat
Definition: enum.c:2562
buf
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4308
rb_assoc_new
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:616
internal.h
minmax_ii_update
static void minmax_ii_update(VALUE i, VALUE j, struct minmax_t *memo)
Definition: enum.c:1374
ID
unsigned long ID
Definition: ruby.h:89
minmax_by_t::min_bv
VALUE min_bv
Definition: enum.c:1559
Qnil
#define Qnil
Definition: ruby.h:427
rb_eStopIteration
VALUE rb_eStopIteration
Definition: enumerator.c:111
VALUE
unsigned long VALUE
Definition: ruby.h:88
enum_collect
static VALUE enum_collect(VALUE obj)
Definition: enum.c:429
id_cmp
#define id_cmp
Definition: enum.c:29
ruby_qsort
void ruby_qsort(void *, const size_t, const size_t, int(*)(const void *, const void *, void *), void *)
enum_to_h_i
static VALUE enum_to_h_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash))
Definition: enum.c:513
result
static VALUE result
Definition: nkf.c:40
RETURN_SIZED_ENUMERATOR
#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn)
Definition: intern.h:237
RBASIC
#define RBASIC(obj)
Definition: ruby.h:1116
enum_min
static VALUE enum_min(VALUE obj)
Definition: enum.c:1226
take_while_i
static VALUE take_while_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
Definition: enum.c:2166
grep_iter_i
static VALUE grep_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
Definition: enum.c:59
minmax_ii
static VALUE minmax_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo))
Definition: enum.c:1395
enum_none
static VALUE enum_none(VALUE obj)
Definition: enum.c:1163
rb_rescue2
VALUE rb_rescue2(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*r_proc)(ANYARGS), VALUE data2,...)
Definition: eval.c:741
rb_ary_new3
#define rb_ary_new3
Definition: intern.h:91
enum_size
static VALUE enum_size(VALUE self, VALUE args, VALUE eobj)
Definition: enum.c:313
rb_check_funcall
VALUE rb_check_funcall(VALUE, ID, int, const VALUE *)
Definition: vm_eval.c:409
INFINITY
#define INFINITY
Definition: missing.h:141
ENUMFUNC
#define ENUMFUNC(name)
Definition: enum.c:1006
enum_one
static VALUE enum_one(VALUE obj)
Definition: enum.c:1127
find_all_i
static VALUE find_all_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
Definition: enum.c:302
enum_drop_while
static VALUE enum_drop_while(VALUE obj)
Definition: enum.c:2274
enum_yield
#define enum_yield
Definition: enum.c:44
LONG2NUM
#define LONG2NUM(x)
Definition: ruby.h:1309
minmax_by_t::max_bv
VALUE max_bv
Definition: enum.c:1560
rb_respond_to
int rb_respond_to(VALUE, ID)
Definition: vm_method.c:1639
minmax_by_t::last_bv
VALUE last_bv
Definition: enum.c:1563
slicebefore_arg::prev_elts
VALUE prev_elts
Definition: enum.c:2564
take_i
static VALUE take_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
Definition: enum.c:2127
id_call
static ID id_call
Definition: enum.c:24
max_i
static VALUE max_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
Definition: enum.c:1243
cycle_i
static VALUE cycle_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
Definition: enum.c:2287
NEW_MEMO
#define NEW_MEMO(a, b, c)
Definition: node.h:466
rb_ary_resize
VALUE rb_ary_resize(VALUE ary, long len)
expands or shrinks ary to len elements.
Definition: array.c:1615
RARRAY_ASET
#define RARRAY_ASET(a, i, v)
Definition: ruby.h:902
sort_by_data::ary
VALUE ary
Definition: enum.c:835
enum_reject
static VALUE enum_reject(VALUE obj)
Definition: enum.c:382
rb_equal
VALUE rb_equal(VALUE, VALUE)
Definition: object.c:89
enum_each_with_object
static VALUE enum_each_with_object(VALUE obj, VALUE memo)
Definition: enum.c:1976
collect_i
static VALUE collect_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
Definition: enum.c:395
size
int size
Definition: encoding.c:49
id_div
static ID id_div
Definition: enum.c:23
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:231
rb_enum_values_pack
VALUE rb_enum_values_pack(int argc, const VALUE *argv)
Definition: enum.c:33
enum_partition
static VALUE enum_partition(VALUE obj)
Definition: enum.c:703
RARRAY_AREF
#define RARRAY_AREF(a, i)
Definition: ruby.h:901
enum_to_a
static VALUE enum_to_a(int argc, VALUE *argv, VALUE obj)
Definition: enum.c:502
mul
#define mul(x, y)
Definition: date_strftime.c:25
max_ii
static VALUE max_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
Definition: enum.c:1263
drop_i
static VALUE drop_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
Definition: enum.c:2200
enum_minmax_by
static VALUE enum_minmax_by(VALUE obj)
Definition: enum.c:1644
rb_block_proc
VALUE rb_block_proc(void)
Definition: proc.c:620
minmax_by_t
Definition: enum.c:1558
enum_reverse_each
static VALUE enum_reverse_each(int argc, VALUE *argv, VALUE obj)
Definition: enum.c:1757
chunk_i
static VALUE chunk_i(RB_BLOCK_CALL_FUNC_ARGLIST(yielder, enumerator))
Definition: enum.c:2424
rb_check_array_type
VALUE rb_check_array_type(VALUE ary)
Definition: array.c:628
minmax_by_t::min
VALUE min
Definition: enum.c:1561
rb_hash_aref
VALUE rb_hash_aref(VALUE hash, VALUE key)
Definition: hash.c:697
RARRAY_PTR
#define RARRAY_PTR(a)
Definition: ruby.h:907
RNode::state
long state
Definition: node.h:258
enum_count
static VALUE enum_count(int argc, VALUE *argv, VALUE obj)
Definition: enum.c:151
minmax_t
Definition: enum.c:1313
LONG2FIX
#define LONG2FIX(i)
Definition: ruby.h:232
RTEST
#define RTEST(v)
Definition: ruby.h:437
rb_thread_check_ints
void rb_thread_check_ints(void)
Definition: thread.c:1139
inject_i
static VALUE inject_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, p))
Definition: enum.c:552
first_i
static VALUE first_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, params))
Definition: enum.c:765
OBJ_INFECT
#define OBJ_INFECT(x, s)
Definition: ruby.h:1180
enum_drop
static VALUE enum_drop(VALUE obj, VALUE n)
Definition: enum.c:2225
partition_i
static VALUE partition_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, arys))
Definition: enum.c:671
enum_find
static VALUE enum_find(int argc, VALUE *argv, VALUE obj)
Definition: enum.c:212
rb_ary_dup
VALUE rb_ary_dup(VALUE ary)
Definition: array.c:1888
zip_i
static VALUE zip_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, memoval))
Definition: enum.c:2029
rb_cArray
VALUE rb_cArray
Definition: array.c:27
rb_ary_concat
VALUE rb_ary_concat(VALUE x, VALUE y)
Definition: array.c:3542
enum_zip
static VALUE enum_zip(int argc, VALUE *argv, VALUE obj)
Definition: enum.c:2088
hash
static unsigned int hash(const char *str, unsigned int len)
Definition: lex.c:56
id_next
static ID id_next
Definition: enum.c:22
enum_min_by
static VALUE enum_min_by(VALUE obj)
Definition: enum.c:1501
RETURN_ENUMERATOR
#define RETURN_ENUMERATOR(obj, argc, argv)
Definition: intern.h:242
zip_ary
static VALUE zip_ary(RB_BLOCK_CALL_FUNC_ARGLIST(val, memoval))
Definition: enum.c:1986
find_index_i
static VALUE find_index_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
Definition: enum.c:231
name
const char * name
Definition: nkf.c:208
ID2SYM
#define ID2SYM(x)
Definition: ruby.h:355
rb_id2name
const char * rb_id2name(ID id)
Definition: ripper.c:17230
chunk_arg
Definition: enum.c:2365
enum_flat_map
static VALUE enum_flat_map(VALUE obj)
Definition: enum.c:476
enum_take_while
static VALUE enum_take_while(VALUE obj)
Definition: enum.c:2189
chunk_arg::prev_elts
VALUE prev_elts
Definition: enum.c:2369
enum_find_index
static VALUE enum_find_index(int argc, VALUE *argv, VALUE obj)
Definition: enum.c:278
enum_minmax
static VALUE enum_minmax(VALUE obj)
Definition: enum.c:1441
each_cons_i
static VALUE each_cons_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
Definition: enum.c:1887
min_i
static VALUE min_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
Definition: enum.c:1171
rb_warning
void rb_warning(const char *fmt,...)
Definition: error.c:236
separator
static VALUE separator
Definition: file.c:4092
CONST_ID
#define CONST_ID(var, str)
Definition: ruby.h:1428
minmax_by_i
static VALUE minmax_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo))
Definition: enum.c:1589
call_stop
static VALUE call_stop(VALUE *v)
Definition: enum.c:2023
find_index_iter_i
static VALUE find_index_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
Definition: enum.c:246
rb_define_module
VALUE rb_define_module(const char *name)
Definition: class.c:746
drop_while_i
static VALUE drop_while_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
Definition: enum.c:2243
reject_i
static VALUE reject_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
Definition: enum.c:354
yielder
Definition: enumerator.c:132
SYMBOL_P
#define SYMBOL_P(x)
Definition: ruby.h:354
enum_each_slice_size
static VALUE enum_each_slice_size(VALUE obj, VALUE args, VALUE eobj)
Definition: enum.c:1839
Qundef
#define Qundef
Definition: ruby.h:428
enum_group_by
static VALUE enum_group_by(VALUE obj)
Definition: enum.c:751
each_val_i
static VALUE each_val_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, p))
Definition: enum.c:1775
STATIC_ASSERT
STATIC_ASSERT(minmax_t, sizeof(struct minmax_t)<=sizeof(NODE)-offsetof(NODE, u1))
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1488
sort_by_data::buf
VALUE buf
Definition: enum.c:836
each_slice_i
static VALUE each_slice_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, m))
Definition: enum.c:1820
minmax_t::min
VALUE min
Definition: enum.c:1314
rb_warn
void rb_warn(const char *fmt,...)
Definition: error.c:223
bp
#define bp()
Definition: vm_debug.h:25
rb_eArgError
VALUE rb_eArgError
Definition: error.c:549
cmp
static ID cmp
Definition: compar.c:16
minmax_by_t::last
VALUE last
Definition: enum.c:1564
call_next
static VALUE call_next(VALUE *v)
Definition: enum.c:2017
NUM2LONG
#define NUM2LONG(x)
Definition: ruby.h:600
rb_attr_get
VALUE rb_attr_get(VALUE, ID)
Definition: variable.c:1127
id_eqq
#define id_eqq
Definition: enum.c:28
argv
char ** argv
Definition: ruby.c:132
DBL2NUM
#define DBL2NUM(dbl)
Definition: ruby.h:815
collect_all
static VALUE collect_all(RB_BLOCK_CALL_FUNC_ARGLIST(i, ary))
Definition: enum.c:403