Ruby 1.9.2p136(2010-12-25revision30365)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# enum.c

Go to the documentation of this file.

    00001 /**********************************************************************
    00002
    00003   enum.c -
    00004
    00005   $Author: yugui $
    00006   created at: Fri Oct  1 15:15:19 JST 1993
    00007
    00008   Copyright (C) 1993-2007 Yukihiro Matsumoto
    00009
    00010 **********************************************************************/
    00011
    00012 #include "ruby/ruby.h"
    00013 #include "ruby/util.h"
    00014 #include "node.h"
    00015
    00016 VALUE rb_mEnumerable;
    00017 static ID id_each, id_eqq, id_cmp, id_next, id_size;
    00018
    00019 static VALUE
    00020 enum_values_pack(int argc, VALUE *argv)
    00021 {
    00022     if (argc == 0) return Qnil;
    00023     if (argc == 1) return argv[0];
    00024     return rb_ary_new4(argc, argv);
    00025 }
    00026
    00027 #define ENUM_WANT_SVALUE() do { \
    00028     i = enum_values_pack(argc, argv); \
    00029 } while (0)
    00030
    00031 #define enum_yield rb_yield_values2
    00032
    00033 static VALUE
    00034 grep_i(VALUE i, VALUE args, int argc, VALUE *argv)
    00035 {
    00036     VALUE *arg = (VALUE *)args;
    00037     ENUM_WANT_SVALUE();
    00038
    00039     if (RTEST(rb_funcall(arg[0], id_eqq, 1, i))) {
    00040         rb_ary_push(arg[1], i);
    00041     }
    00042     return Qnil;
    00043 }
    00044
    00045 static VALUE
    00046 grep_iter_i(VALUE i, VALUE args, int argc, VALUE *argv)
    00047 {
    00048     VALUE *arg = (VALUE *)args;
    00049     ENUM_WANT_SVALUE();
    00050
    00051     if (RTEST(rb_funcall(arg[0], id_eqq, 1, i))) {
    00052         rb_ary_push(arg[1], rb_yield(i));
    00053     }
    00054     return Qnil;
    00055 }
    00056
    00057 /*
    00058  *  call-seq:
    00059  *     enum.grep(pattern)                   -> array
    00060  *     enum.grep(pattern) {| obj | block }  -> array
    00061  *
    00062  *  Returns an array of every element in <i>enum</i> for which
    00063  *  <code>Pattern === element</code>. If the optional <em>block</em> is
    00064  *  supplied, each matching element is passed to it, and the block's
    00065  *  result is stored in the output array.
    00066  *
    00067  *     (1..100).grep 38..44   #=> [38, 39, 40, 41, 42, 43, 44]
    00068  *     c = IO.constants
    00069  *     c.grep(/SEEK/)         #=> [:SEEK_SET, :SEEK_CUR, :SEEK_END]
    00070  *     res = c.grep(/SEEK/) {|v| IO.const_get(v) }
    00071  *     res                    #=> [0, 1, 2]
    00072  *
    00073  */
    00074
    00075 static VALUE
    00076 enum_grep(VALUE obj, VALUE pat)
    00077 {
    00078     VALUE ary = rb_ary_new();
    00079     VALUE arg[2];
    00080
    00081     arg[0] = pat;
    00082     arg[1] = ary;
    00083
    00084     rb_block_call(obj, id_each, 0, 0, rb_block_given_p() ? grep_iter_i : grep_i, (VALUE)arg);
    00085
    00086     return ary;
    00087 }
    00088
    00089 static VALUE
    00090 count_i(VALUE i, VALUE memop, int argc, VALUE *argv)
    00091 {
    00092     VALUE *memo = (VALUE*)memop;
    00093
    00094     ENUM_WANT_SVALUE();
    00095
    00096     if (rb_equal(i, memo[1])) {
    00097         memo[0]++;
    00098     }
    00099     return Qnil;
    00100 }
    00101
    00102 static VALUE
    00103 count_iter_i(VALUE i, VALUE memop, int argc, VALUE *argv)
    00104 {
    00105     VALUE *memo = (VALUE*)memop;
    00106
    00107     if (RTEST(enum_yield(argc, argv))) {
    00108         memo[0]++;
    00109     }
    00110     return Qnil;
    00111 }
    00112
    00113 static VALUE
    00114 count_all_i(VALUE i, VALUE memop, int argc, VALUE *argv)
    00115 {
    00116     VALUE *memo = (VALUE*)memop;
    00117
    00118     memo[0]++;
    00119     return Qnil;
    00120 }
    00121
    00122 /*
    00123  *  call-seq:
    00124  *     enum.count                   -> int
    00125  *     enum.count(item)             -> int
    00126  *     enum.count {| obj | block }  -> int
    00127  *
    00128  *  Returns the number of items in <i>enum</i>, where #size is called
    00129  *  if it responds to it, otherwise the items are counted through
    00130  *  enumeration.  If an argument is given, counts the number of items
    00131  *  in <i>enum</i>, for which equals to <i>item</i>.  If a block is
    00132  *  given, counts the number of elements yielding a true value.
    00133  *
    00134  *     ary = [1, 2, 4, 2]
    00135  *     ary.count             #=> 4
    00136  *     ary.count(2)          #=> 2
    00137  *     ary.count{|x|x%2==0}  #=> 3
    00138  *
    00139  */
    00140
    00141 static VALUE
    00142 enum_count(int argc, VALUE *argv, VALUE obj)
    00143 {
    00144     VALUE memo[2];      /* [count, condition value] */
    00145     rb_block_call_func *func;
    00146
    00147     if (argc == 0) {
    00148         if (rb_block_given_p()) {
    00149             func = count_iter_i;
    00150         }
    00151         else {
    00152             func = count_all_i;
    00153         }
    00154     }
    00155     else {
    00156         rb_scan_args(argc, argv, "1", &memo[1]);
    00157         if (rb_block_given_p()) {
    00158             rb_warn("given block not used");
    00159         }
    00160         func = count_i;
    00161     }
    00162
    00163     memo[0] = 0;
    00164     rb_block_call(obj, id_each, 0, 0, func, (VALUE)&memo);
    00165     return INT2NUM(memo[0]);
    00166 }
    00167
    00168 static VALUE
    00169 find_i(VALUE i, VALUE *memo, int argc, VALUE *argv)
    00170 {
    00171     ENUM_WANT_SVALUE();
    00172
    00173     if (RTEST(rb_yield(i))) {
    00174         *memo = i;
    00175         rb_iter_break();
    00176     }
    00177     return Qnil;
    00178 }
    00179
    00180 /*
    00181  *  call-seq:
    00182  *     enum.detect(ifnone = nil) {| obj | block }  -> obj or nil
    00183  *     enum.find(ifnone = nil)   {| obj | block }  -> obj or nil
    00184  *     enum.detect(ifnone = nil)                   -> an_enumerator
    00185  *     enum.find(ifnone = nil)                     -> an_enumerator
    00186  *
    00187  *  Passes each entry in <i>enum</i> to <em>block</em>. Returns the
    00188  *  first for which <em>block</em> is not false.  If no
    00189  *  object matches, calls <i>ifnone</i> and returns its result when it
    00190  *  is specified, or returns <code>nil</code> otherwise.
    00191  *
    00192  *  If no block is given, an enumerator is returned instead.
    00193  *
    00194  *     (1..10).detect  {|i| i % 5 == 0 and i % 7 == 0 }   #=> nil
    00195  *     (1..100).detect {|i| i % 5 == 0 and i % 7 == 0 }   #=> 35
    00196  *
    00197  */
    00198
    00199 static VALUE
    00200 enum_find(int argc, VALUE *argv, VALUE obj)
    00201 {
    00202     VALUE memo = Qundef;
    00203     VALUE if_none;
    00204
    00205     rb_scan_args(argc, argv, "01", &if_none);
    00206     RETURN_ENUMERATOR(obj, argc, argv);
    00207     rb_block_call(obj, id_each, 0, 0, find_i, (VALUE)&memo);
    00208     if (memo != Qundef) {
    00209         return memo;
    00210     }
    00211     if (!NIL_P(if_none)) {
    00212         return rb_funcall(if_none, rb_intern("call"), 0, 0);
    00213     }
    00214     return Qnil;
    00215 }
    00216
    00217 static VALUE
    00218 find_index_i(VALUE i, VALUE memop, int argc, VALUE *argv)
    00219 {
    00220     VALUE *memo = (VALUE*)memop;
    00221
    00222     ENUM_WANT_SVALUE();
    00223
    00224     if (rb_equal(i, memo[2])) {
    00225         memo[0] = UINT2NUM(memo[1]);
    00226         rb_iter_break();
    00227     }
    00228     memo[1]++;
    00229     return Qnil;
    00230 }
    00231
    00232 static VALUE
    00233 find_index_iter_i(VALUE i, VALUE memop, int argc, VALUE *argv)
    00234 {
    00235     VALUE *memo = (VALUE*)memop;
    00236
    00237     if (RTEST(enum_yield(argc, argv))) {
    00238         memo[0] = UINT2NUM(memo[1]);
    00239         rb_iter_break();
    00240     }
    00241     memo[1]++;
    00242     return Qnil;
    00243 }
    00244
    00245 /*
    00246  *  call-seq:
    00247  *     enum.find_index(value)            -> int or nil
    00248  *     enum.find_index {| obj | block }  -> int or nil
    00249  *     enum.find_index                   -> an_enumerator
    00250  *
    00251  *  Compares each entry in <i>enum</i> with <em>value</em> or passes
    00252  *  to <em>block</em>.  Returns the index for the first for which the
    00253  *  evaluated value is non-false.  If no object matches, returns
    00254  *  <code>nil</code>
    00255  *
    00256  *  If neither block nor argument is given, an enumerator is returned instead.
    00257  *
    00258  *     (1..10).find_index  {|i| i % 5 == 0 and i % 7 == 0 }   #=> nil
    00259  *     (1..100).find_index {|i| i % 5 == 0 and i % 7 == 0 }   #=> 34
    00260  *     (1..100).find_index(50)                                #=> 49
    00261  *
    00262  */
    00263
    00264 static VALUE
    00265 enum_find_index(int argc, VALUE *argv, VALUE obj)
    00266 {
    00267     VALUE memo[3];      /* [return value, current index, condition value] */
    00268     rb_block_call_func *func;
    00269
    00270     if (argc == 0) {
    00271         RETURN_ENUMERATOR(obj, 0, 0);
    00272         func = find_index_iter_i;
    00273     }
    00274     else {
    00275         rb_scan_args(argc, argv, "1", &memo[2]);
    00276         if (rb_block_given_p()) {
    00277             rb_warn("given block not used");
    00278         }
    00279         func = find_index_i;
    00280     }
    00281
    00282     memo[0] = Qnil;
    00283     memo[1] = 0;
    00284     rb_block_call(obj, id_each, 0, 0, func, (VALUE)memo);
    00285     return memo[0];
    00286 }
    00287
    00288 static VALUE
    00289 find_all_i(VALUE i, VALUE ary, int argc, VALUE *argv)
    00290 {
    00291     ENUM_WANT_SVALUE();
    00292
    00293     if (RTEST(rb_yield(i))) {
    00294         rb_ary_push(ary, i);
    00295     }
    00296     return Qnil;
    00297 }
    00298
    00299 /*
    00300  *  call-seq:
    00301  *     enum.find_all {| obj | block }  -> array
    00302  *     enum.select   {| obj | block }  -> array
    00303  *     enum.find_all                   -> an_enumerator
    00304  *     enum.select                     -> an_enumerator
    00305  *
    00306  *  Returns an array containing all elements of <i>enum</i> for which
    00307  *  <em>block</em> is not <code>false</code> (see also
    00308  *  <code>Enumerable#reject</code>).
    00309  *
    00310  *  If no block is given, an enumerator is returned instead.
    00311  *
    00312  *
    00313  *     (1..10).find_all {|i|  i % 3 == 0 }   #=> [3, 6, 9]
    00314  *
    00315  */
    00316
    00317 static VALUE
    00318 enum_find_all(VALUE obj)
    00319 {
    00320     VALUE ary;
    00321
    00322     RETURN_ENUMERATOR(obj, 0, 0);
    00323
    00324     ary = rb_ary_new();
    00325     rb_block_call(obj, id_each, 0, 0, find_all_i, ary);
    00326
    00327     return ary;
    00328 }
    00329
    00330 static VALUE
    00331 reject_i(VALUE i, VALUE ary, int argc, VALUE *argv)
    00332 {
    00333     ENUM_WANT_SVALUE();
    00334
    00335     if (!RTEST(rb_yield(i))) {
    00336         rb_ary_push(ary, i);
    00337     }
    00338     return Qnil;
    00339 }
    00340
    00341 /*
    00342  *  call-seq:
    00343  *     enum.reject {| obj | block }  -> array
    00344  *     enum.reject                   -> an_enumerator
    00345  *
    00346  *  Returns an array for all elements of <i>enum</i> for which
    00347  *  <em>block</em> is false (see also <code>Enumerable#find_all</code>).
    00348  *
    00349  *  If no block is given, an enumerator is returned instead.
    00350  *
    00351  *     (1..10).reject {|i|  i % 3 == 0 }   #=> [1, 2, 4, 5, 7, 8, 10]
    00352  *
    00353  */
    00354
    00355 static VALUE
    00356 enum_reject(VALUE obj)
    00357 {
    00358     VALUE ary;
    00359
    00360     RETURN_ENUMERATOR(obj, 0, 0);
    00361
    00362     ary = rb_ary_new();
    00363     rb_block_call(obj, id_each, 0, 0, reject_i, ary);
    00364
    00365     return ary;
    00366 }
    00367
    00368 static VALUE
    00369 collect_i(VALUE i, VALUE ary, int argc, VALUE *argv)
    00370 {
    00371     rb_ary_push(ary, enum_yield(argc, argv));
    00372
    00373     return Qnil;
    00374 }
    00375
    00376 static VALUE
    00377 collect_all(VALUE i, VALUE ary, int argc, VALUE *argv)
    00378 {
    00379     rb_thread_check_ints();
    00380     rb_ary_push(ary, enum_values_pack(argc, argv));
    00381
    00382     return Qnil;
    00383 }
    00384
    00385 /*
    00386  *  call-seq:
    00387  *     enum.collect {| obj | block }  -> array
    00388  *     enum.map     {| obj | block }  -> array
    00389  *     enum.collect                   -> an_enumerator
    00390  *     enum.map                       -> an_enumerator
    00391  *
    00392  *  Returns a new array with the results of running <em>block</em> once
    00393  *  for every element in <i>enum</i>.
    00394  *
    00395  *  If no block is given, an enumerator is returned instead.
    00396  *
    00397  *     (1..4).collect {|i| i*i }   #=> [1, 4, 9, 16]
    00398  *     (1..4).collect { "cat"  }   #=> ["cat", "cat", "cat", "cat"]
    00399  *
    00400  */
    00401
    00402 static VALUE
    00403 enum_collect(VALUE obj)
    00404 {
    00405     VALUE ary;
    00406
    00407     RETURN_ENUMERATOR(obj, 0, 0);
    00408
    00409     ary = rb_ary_new();
    00410     rb_block_call(obj, id_each, 0, 0, collect_i, ary);
    00411
    00412     return ary;
    00413 }
    00414
    00415 static VALUE
    00416 flat_map_i(VALUE i, VALUE ary, int argc, VALUE *argv)
    00417 {
    00418     VALUE tmp;
    00419
    00420     i = enum_yield(argc, argv);
    00421     tmp = rb_check_array_type(i);
    00422
    00423     if (NIL_P(tmp)) {
    00424         rb_ary_push(ary, i);
    00425     }
    00426     else {
    00427         rb_ary_concat(ary, tmp);
    00428     }
    00429     return Qnil;
    00430 }
    00431
    00432 /*
    00433  *  call-seq:
    00434  *     enum.flat_map       {| obj | block }  -> array
    00435  *     enum.collect_concat {| obj | block }  -> array
    00436  *     enum.flat_map                         -> an_enumerator
    00437  *     enum.collect_concat                   -> an_enumerator
    00438  *
    00439  *  Returns a new array with the concatenated results of running
    00440  *  <em>block</em> once for every element in <i>enum</i>.
    00441  *
    00442  *  If no block is given, an enumerator is returned instead.
    00443  *
    00444  *     [[1,2],[3,4]].flat_map {|i| i }   #=> [1, 2, 3, 4]
    00445  *
    00446  */
    00447
    00448 static VALUE
    00449 enum_flat_map(VALUE obj)
    00450 {
    00451     VALUE ary;
    00452
    00453     RETURN_ENUMERATOR(obj, 0, 0);
    00454
    00455     ary = rb_ary_new();
    00456     rb_block_call(obj, id_each, 0, 0, flat_map_i, ary);
    00457
    00458     return ary;
    00459 }
    00460
    00461 /*
    00462  *  call-seq:
    00463  *     enum.to_a      ->    array
    00464  *     enum.entries   ->    array
    00465  *
    00466  *  Returns an array containing the items in <i>enum</i>.
    00467  *
    00468  *     (1..7).to_a                       #=> [1, 2, 3, 4, 5, 6, 7]
    00469  *     { 'a'=>1, 'b'=>2, 'c'=>3 }.to_a   #=> [["a", 1], ["b", 2], ["c", 3]]
    00470  */
    00471 static VALUE
    00472 enum_to_a(int argc, VALUE *argv, VALUE obj)
    00473 {
    00474     VALUE ary = rb_ary_new();
    00475
    00476     rb_block_call(obj, id_each, argc, argv, collect_all, ary);
    00477     OBJ_INFECT(ary, obj);
    00478
    00479     return ary;
    00480 }
    00481
    00482 static VALUE
    00483 inject_i(VALUE i, VALUE p, int argc, VALUE *argv)
    00484 {
    00485     VALUE *memo = (VALUE *)p;
    00486
    00487     ENUM_WANT_SVALUE();
    00488
    00489     if (memo[0] == Qundef) {
    00490         memo[0] = i;
    00491     }
    00492     else {
    00493         memo[0] = rb_yield_values(2, memo[0], i);
    00494     }
    00495     return Qnil;
    00496 }
    00497
    00498 static VALUE
    00499 inject_op_i(VALUE i, VALUE p, int argc, VALUE *argv)
    00500 {
    00501     VALUE *memo = (VALUE *)p;
    00502
    00503     ENUM_WANT_SVALUE();
    00504
    00505     if (memo[0] == Qundef) {
    00506         memo[0] = i;
    00507     }
    00508     else {
    00509         memo[0] = rb_funcall(memo[0], (ID)memo[1], 1, i);
    00510     }
    00511     return Qnil;
    00512 }
    00513
    00514 /*
    00515  *  call-seq:
    00516  *     enum.inject(initial, sym) -> obj
    00517  *     enum.inject(sym)          -> obj
    00518  *     enum.inject(initial) {| memo, obj | block }  -> obj
    00519  *     enum.inject          {| memo, obj | block }  -> obj
    00520  *
    00521  *     enum.reduce(initial, sym) -> obj
    00522  *     enum.reduce(sym)          -> obj
    00523  *     enum.reduce(initial) {| memo, obj | block }  -> obj
    00524  *     enum.reduce          {| memo, obj | block }  -> obj
    00525  *
    00526  *  Combines all elements of <i>enum</i> by applying a binary
    00527  *  operation, specified by a block or a symbol that names a
    00528  *  method or operator.
    00529  *
    00530  *  If you specify a block, then for each element in <i>enum</i>
    00531  *  the block is passed an accumulator value (<i>memo</i>) and the element.
    00532  *  If you specify a symbol instead, then each element in the collection
    00533  *  will be passed to the named method of <i>memo</i>.
    00534  *  In either case, the result becomes the new value for <i>memo</i>.
    00535  *  At the end of the iteration, the final value of <i>memo</i> is the
    00536  *  return value fo the method.
    00537  *
    00538  *  If you do not explicitly specify an <i>initial</i> value for <i>memo</i>,
    00539  *  then uses the first element of collection is used as the initial value
    00540  *  of <i>memo</i>.
    00541  *
    00542  *  Examples:
    00543  *
    00544  *     # Sum some numbers
    00545  *     (5..10).reduce(:+)                            #=> 45
    00546  *     # Same using a block and inject
    00547  *     (5..10).inject {|sum, n| sum + n }            #=> 45
    00548  *     # Multiply some numbers
    00549  *     (5..10).reduce(1, :*)                         #=> 151200
    00550  *     # Same using a block
    00551  *     (5..10).inject(1) {|product, n| product * n } #=> 151200
    00552  *     # find the longest word
    00553  *     longest = %w{ cat sheep bear }.inject do |memo,word|
    00554  *        memo.length > word.length ? memo : word
    00555  *     end
    00556  *     longest                                       #=> "sheep"
    00557  *
    00558  */
    00559 static VALUE
    00560 enum_inject(int argc, VALUE *argv, VALUE obj)
    00561 {
    00562     VALUE memo[2];
    00563     VALUE (*iter)(VALUE, VALUE, int, VALUE*) = inject_i;
    00564
    00565     switch (rb_scan_args(argc, argv, "02", &memo[0], &memo[1])) {
    00566       case 0:
    00567         memo[0] = Qundef;
    00568         break;
    00569       case 1:
    00570         if (rb_block_given_p()) {
    00571             break;
    00572         }
    00573         memo[1] = (VALUE)rb_to_id(memo[0]);
    00574         memo[0] = Qundef;
    00575         iter = inject_op_i;
    00576         break;
    00577       case 2:
    00578         if (rb_block_given_p()) {
    00579             rb_warning("given block not used");
    00580         }
    00581         memo[1] = (VALUE)rb_to_id(memo[1]);
    00582         iter = inject_op_i;
    00583         break;
    00584     }
    00585     rb_block_call(obj, id_each, 0, 0, iter, (VALUE)memo);
    00586     if (memo[0] == Qundef) return Qnil;
    00587     return memo[0];
    00588 }
    00589
    00590 static VALUE
    00591 partition_i(VALUE i, VALUE *ary, int argc, VALUE *argv)
    00592 {
    00593     ENUM_WANT_SVALUE();
    00594
    00595     if (RTEST(rb_yield(i))) {
    00596         rb_ary_push(ary[0], i);
    00597     }
    00598     else {
    00599         rb_ary_push(ary[1], i);
    00600     }
    00601     return Qnil;
    00602 }
    00603
    00604 /*
    00605  *  call-seq:
    00606  *     enum.partition {| obj | block }  -> [ true_array, false_array ]
    00607  *     enum.partition                   -> an_enumerator
    00608  *
    00609  *  Returns two arrays, the first containing the elements of
    00610  *  <i>enum</i> for which the block evaluates to true, the second
    00611  *  containing the rest.
    00612  *
    00613  *  If no block is given, an enumerator is returned instead.
    00614  *
    00615  *     (1..6).partition {|i| (i&1).zero?}   #=> [[2, 4, 6], [1, 3, 5]]
    00616  *
    00617  */
    00618
    00619 static VALUE
    00620 enum_partition(VALUE obj)
    00621 {
    00622     VALUE ary[2];
    00623
    00624     RETURN_ENUMERATOR(obj, 0, 0);
    00625
    00626     ary[0] = rb_ary_new();
    00627     ary[1] = rb_ary_new();
    00628     rb_block_call(obj, id_each, 0, 0, partition_i, (VALUE)ary);
    00629
    00630     return rb_assoc_new(ary[0], ary[1]);
    00631 }
    00632
    00633 static VALUE
    00634 group_by_i(VALUE i, VALUE hash, int argc, VALUE *argv)
    00635 {
    00636     VALUE group;
    00637     VALUE values;
    00638
    00639     ENUM_WANT_SVALUE();
    00640
    00641     group = rb_yield(i);
    00642     values = rb_hash_aref(hash, group);
    00643     if (NIL_P(values)) {
    00644         values = rb_ary_new3(1, i);
    00645         rb_hash_aset(hash, group, values);
    00646     }
    00647     else {
    00648         rb_ary_push(values, i);
    00649     }
    00650     return Qnil;
    00651 }
    00652
    00653 /*
    00654  *  call-seq:
    00655  *     enum.group_by {| obj | block }  -> a_hash
    00656  *     enum.group_by                   -> an_enumerator
    00657  *
    00658  *  Returns a hash, which keys are evaluated result from the
    00659  *  block, and values are arrays of elements in <i>enum</i>
    00660  *  corresponding to the key.
    00661  *
    00662  *  If no block is given, an enumerator is returned instead.
    00663  *
    00664  *     (1..6).group_by {|i| i%3}   #=> {0=>[3, 6], 1=>[1, 4], 2=>[2, 5]}
    00665  *
    00666  */
    00667
    00668 static VALUE
    00669 enum_group_by(VALUE obj)
    00670 {
    00671     VALUE hash;
    00672
    00673     RETURN_ENUMERATOR(obj, 0, 0);
    00674
    00675     hash = rb_hash_new();
    00676     rb_block_call(obj, id_each, 0, 0, group_by_i, hash);
    00677     OBJ_INFECT(hash, obj);
    00678
    00679     return hash;
    00680 }
    00681
    00682 static VALUE
    00683 first_i(VALUE i, VALUE *params, int argc, VALUE *argv)
    00684 {
    00685     ENUM_WANT_SVALUE();
    00686
    00687     if (NIL_P(params[1])) {
    00688         params[1] = i;
    00689         rb_iter_break();
    00690     }
    00691     else {
    00692         long n = params[0];
    00693
    00694         rb_ary_push(params[1], i);
    00695         n--;
    00696         if (n <= 0) {
    00697             rb_iter_break();
    00698         }
    00699         params[0] = n;
    00700     }
    00701     return Qnil;
    00702 }
    00703
    00704 /*
    00705  *  call-seq:
    00706  *     enum.first       ->  obj or nil
    00707  *     enum.first(n)    ->  an_array
    00708  *
    00709  *  Returns the first element, or the first +n+ elements, of the enumerable.
    00710  *  If the enumerable is empty, the first form returns <code>nil</code>, and the
    00711  *  second form returns an empty array.
    00712  *
    00713  */
    00714
    00715 static VALUE
    00716 enum_first(int argc, VALUE *argv, VALUE obj)
    00717 {
    00718     VALUE n, params[2];
    00719
    00720     if (argc == 0) {
    00721         params[0] = params[1] = Qnil;
    00722     }
    00723     else {
    00724         long len;
    00725
    00726         rb_scan_args(argc, argv, "01", &n);
    00727         len = NUM2LONG(n);
    00728         if (len == 0) return rb_ary_new2(0);
    00729         if (len < 0) {
    00730             rb_raise(rb_eArgError, "negative length");
    00731         }
    00732         params[0] = len;
    00733         params[1] = rb_ary_new2(len);
    00734     }
    00735     rb_block_call(obj, id_each, 0, 0, first_i, (VALUE)params);
    00736
    00737     return params[1];
    00738 }
    00739
    00740
    00741 /*
    00742  *  call-seq:
    00743  *     enum.sort                     -> array
    00744  *     enum.sort {| a, b | block }   -> array
    00745  *
    00746  *  Returns an array containing the items in <i>enum</i> sorted,
    00747  *  either according to their own <code><=></code> method, or by using
    00748  *  the results of the supplied block. The block should return -1, 0, or
    00749  *  +1 depending on the comparison between <i>a</i> and <i>b</i>. As of
    00750  *  Ruby 1.8, the method <code>Enumerable#sort_by</code> implements a
    00751  *  built-in Schwartzian Transform, useful when key computation or
    00752  *  comparison is expensive.
    00753  *
    00754  *     %w(rhea kea flea).sort         #=> ["flea", "kea", "rhea"]
    00755  *     (1..10).sort {|a,b| b <=> a}   #=> [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
    00756  */
    00757
    00758 static VALUE
    00759 enum_sort(VALUE obj)
    00760 {
    00761     return rb_ary_sort(enum_to_a(0, 0, obj));
    00762 }
    00763
    00764 static VALUE
    00765 sort_by_i(VALUE i, VALUE ary, int argc, VALUE *argv)
    00766 {
    00767     NODE *memo;
    00768
    00769     ENUM_WANT_SVALUE();
    00770
    00771     if (RBASIC(ary)->klass) {
    00772         rb_raise(rb_eRuntimeError, "sort_by reentered");
    00773     }
    00774     /* use NODE_DOT2 as memo(v, v, -) */
    00775     memo = rb_node_newnode(NODE_DOT2, rb_yield(i), i, 0);
    00776     rb_ary_push(ary, (VALUE)memo);
    00777     return Qnil;
    00778 }
    00779
    00780 static int
    00781 sort_by_cmp(const void *ap, const void *bp, void *data)
    00782 {
    00783     VALUE a = (*(NODE *const *)ap)->u1.value;
    00784     VALUE b = (*(NODE *const *)bp)->u1.value;
    00785     VALUE ary = (VALUE)data;
    00786
    00787     if (RBASIC(ary)->klass) {
    00788         rb_raise(rb_eRuntimeError, "sort_by reentered");
    00789     }
    00790     return rb_cmpint(rb_funcall(a, id_cmp, 1, b), a, b);
    00791 }
    00792
    00793 /*
    00794  *  call-seq:
    00795  *     enum.sort_by {| obj | block }    -> array
    00796  *     enum.sort_by                     -> an_enumerator
    00797  *
    00798  *  Sorts <i>enum</i> using a set of keys generated by mapping the
    00799  *  values in <i>enum</i> through the given block.
    00800  *
    00801  *  If no block is given, an enumerator is returned instead.
    00802  *
    00803  *     %w{ apple pear fig }.sort_by {|word| word.length}
    00804  *                   #=> ["fig", "pear", "apple"]
    00805  *
    00806  *  The current implementation of <code>sort_by</code> generates an
    00807  *  array of tuples containing the original collection element and the
    00808  *  mapped value. This makes <code>sort_by</code> fairly expensive when
    00809  *  the keysets are simple
    00810  *
    00811  *     require 'benchmark'
    00812  *
    00813  *     a = (1..100000).map {rand(100000)}
    00814  *
    00815  *     Benchmark.bm(10) do |b|
    00816  *       b.report("Sort")    { a.sort }
    00817  *       b.report("Sort by") { a.sort_by {|a| a} }
    00818  *     end
    00819  *
    00820  *  <em>produces:</em>
    00821  *
    00822  *     user     system      total        real
    00823  *     Sort        0.180000   0.000000   0.180000 (  0.175469)
    00824  *     Sort by     1.980000   0.040000   2.020000 (  2.013586)
    00825  *
    00826  *  However, consider the case where comparing the keys is a non-trivial
    00827  *  operation. The following code sorts some files on modification time
    00828  *  using the basic <code>sort</code> method.
    00829  *
    00830  *     files = Dir["*"]
    00831  *     sorted = files.sort {|a,b| File.new(a).mtime <=> File.new(b).mtime}
    00832  *     sorted   #=> ["mon", "tues", "wed", "thurs"]
    00833  *
    00834  *  This sort is inefficient: it generates two new <code>File</code>
    00835  *  objects during every comparison. A slightly better technique is to
    00836  *  use the <code>Kernel#test</code> method to generate the modification
    00837  *  times directly.
    00838  *
    00839  *     files = Dir["*"]
    00840  *     sorted = files.sort { |a,b|
    00841  *       test(?M, a) <=> test(?M, b)
    00842  *     }
    00843  *     sorted   #=> ["mon", "tues", "wed", "thurs"]
    00844  *
    00845  *  This still generates many unnecessary <code>Time</code> objects. A
    00846  *  more efficient technique is to cache the sort keys (modification
    00847  *  times in this case) before the sort. Perl users often call this
    00848  *  approach a Schwartzian Transform, after Randal Schwartz. We
    00849  *  construct a temporary array, where each element is an array
    00850  *  containing our sort key along with the filename. We sort this array,
    00851  *  and then extract the filename from the result.
    00852  *
    00853  *     sorted = Dir["*"].collect { |f|
    00854  *        [test(?M, f), f]
    00855  *     }.sort.collect { |f| f[1] }
    00856  *     sorted   #=> ["mon", "tues", "wed", "thurs"]
    00857  *
    00858  *  This is exactly what <code>sort_by</code> does internally.
    00859  *
    00860  *     sorted = Dir["*"].sort_by {|f| test(?M, f)}
    00861  *     sorted   #=> ["mon", "tues", "wed", "thurs"]
    00862  */
    00863
    00864 static VALUE
    00865 enum_sort_by(VALUE obj)
    00866 {
    00867     VALUE ary;
    00868     long i;
    00869
    00870     RETURN_ENUMERATOR(obj, 0, 0);
    00871
    00872     if (TYPE(obj) == T_ARRAY) {
    00873         ary  = rb_ary_new2(RARRAY_LEN(obj));
    00874     }
    00875     else {
    00876         ary = rb_ary_new();
    00877     }
    00878     RBASIC(ary)->klass = 0;
    00879     rb_block_call(obj, id_each, 0, 0, sort_by_i, ary);
    00880     if (RARRAY_LEN(ary) > 1) {
    00881         ruby_qsort(RARRAY_PTR(ary), RARRAY_LEN(ary), sizeof(VALUE),
    00882                    sort_by_cmp, (void *)ary);
    00883     }
    00884     if (RBASIC(ary)->klass) {
    00885         rb_raise(rb_eRuntimeError, "sort_by reentered");
    00886     }
    00887     for (i=0; i<RARRAY_LEN(ary); i++) {
    00888         RARRAY_PTR(ary)[i] = RNODE(RARRAY_PTR(ary)[i])->u2.value;
    00889     }
    00890     RBASIC(ary)->klass = rb_cArray;
    00891     OBJ_INFECT(ary, obj);
    00892
    00893     return ary;
    00894 }
    00895
    00896 #define ENUMFUNC(name) rb_block_given_p() ? name##_iter_i : name##_i
    00897
    00898 #define DEFINE_ENUMFUNCS(name) \
    00899 static VALUE enum_##name##_func(VALUE result, VALUE *memo); \
    00900 \
    00901 static VALUE \
    00902 name##_i(VALUE i, VALUE *memo, int argc, VALUE *argv) \
    00903 { \
    00904     return enum_##name##_func(enum_values_pack(argc, argv), memo); \
    00905 } \
    00906 \
    00907 static VALUE \
    00908 name##_iter_i(VALUE i, VALUE *memo, int argc, VALUE *argv) \
    00909 { \
    00910     return enum_##name##_func(enum_yield(argc, argv), memo); \
    00911 } \
    00912 \
    00913 static VALUE \
    00914 enum_##name##_func(VALUE result, VALUE *memo)
    00915
    00916 DEFINE_ENUMFUNCS(all)
    00917 {
    00918     if (!RTEST(result)) {
    00919         *memo = Qfalse;
    00920         rb_iter_break();
    00921     }
    00922     return Qnil;
    00923 }
    00924
    00925 /*
    00926  *  call-seq:
    00927  *     enum.all? [{|obj| block } ]   -> true or false
    00928  *
    00929  *  Passes each element of the collection to the given block. The method
    00930  *  returns <code>true</code> if the block never returns
    00931  *  <code>false</code> or <code>nil</code>. If the block is not given,
    00932  *  Ruby adds an implicit block of <code>{|obj| obj}</code> (that is
    00933  *  <code>all?</code> will return <code>true</code> only if none of the
    00934  *  collection members are <code>false</code> or <code>nil</code>.)
    00935  *
    00936  *     %w{ant bear cat}.all? {|word| word.length >= 3}   #=> true
    00937  *     %w{ant bear cat}.all? {|word| word.length >= 4}   #=> false
    00938  *     [ nil, true, 99 ].all?                            #=> false
    00939  *
    00940  */
    00941
    00942 static VALUE
    00943 enum_all(VALUE obj)
    00944 {
    00945     VALUE result = Qtrue;
    00946
    00947     rb_block_call(obj, id_each, 0, 0, ENUMFUNC(all), (VALUE)&result);
    00948     return result;
    00949 }
    00950
    00951 DEFINE_ENUMFUNCS(any)
    00952 {
    00953     if (RTEST(result)) {
    00954         *memo = Qtrue;
    00955         rb_iter_break();
    00956     }
    00957     return Qnil;
    00958 }
    00959
    00960 /*
    00961  *  call-seq:
    00962  *     enum.any? [{|obj| block } ]   -> true or false
    00963  *
    00964  *  Passes each element of the collection to the given block. The method
    00965  *  returns <code>true</code> if the block ever returns a value other
    00966  *  than <code>false</code> or <code>nil</code>. If the block is not
    00967  *  given, Ruby adds an implicit block of <code>{|obj| obj}</code> (that
    00968  *  is <code>any?</code> will return <code>true</code> if at least one
    00969  *  of the collection members is not <code>false</code> or
    00970  *  <code>nil</code>.
    00971  *
    00972  *     %w{ant bear cat}.any? {|word| word.length >= 3}   #=> true
    00973  *     %w{ant bear cat}.any? {|word| word.length >= 4}   #=> true
    00974  *     [ nil, true, 99 ].any?                            #=> true
    00975  *
    00976  */
    00977
    00978 static VALUE
    00979 enum_any(VALUE obj)
    00980 {
    00981     VALUE result = Qfalse;
    00982
    00983     rb_block_call(obj, id_each, 0, 0, ENUMFUNC(any), (VALUE)&result);
    00984     return result;
    00985 }
    00986
    00987 DEFINE_ENUMFUNCS(one)
    00988 {
    00989     if (RTEST(result)) {
    00990         if (*memo == Qundef) {
    00991             *memo = Qtrue;
    00992         }
    00993         else if (*memo == Qtrue) {
    00994             *memo = Qfalse;
    00995             rb_iter_break();
    00996         }
    00997     }
    00998     return Qnil;
    00999 }
    01000
    01001 /*
    01002  *  call-seq:
    01003  *     enum.one? [{|obj| block }]   -> true or false
    01004  *
    01005  *  Passes each element of the collection to the given block. The method
    01006  *  returns <code>true</code> if the block returns <code>true</code>
    01007  *  exactly once. If the block is not given, <code>one?</code> will return
    01008  *  <code>true</code> only if exactly one of the collection members is
    01009  *  true.
    01010  *
    01011  *     %w{ant bear cat}.one? {|word| word.length == 4}   #=> true
    01012  *     %w{ant bear cat}.one? {|word| word.length > 4}    #=> false
    01013  *     %w{ant bear cat}.one? {|word| word.length < 4}    #=> false
    01014  *     [ nil, true, 99 ].one?                            #=> false
    01015  *     [ nil, true, false ].one?                         #=> true
    01016  *
    01017  */
    01018
    01019 static VALUE
    01020 enum_one(VALUE obj)
    01021 {
    01022     VALUE result = Qundef;
    01023
    01024     rb_block_call(obj, id_each, 0, 0, ENUMFUNC(one), (VALUE)&result);
    01025     if (result == Qundef) return Qfalse;
    01026     return result;
    01027 }
    01028
    01029 DEFINE_ENUMFUNCS(none)
    01030 {
    01031     if (RTEST(result)) {
    01032         *memo = Qfalse;
    01033         rb_iter_break();
    01034     }
    01035     return Qnil;
    01036 }
    01037
    01038 /*
    01039  *  call-seq:
    01040  *     enum.none? [{|obj| block }]   -> true or false
    01041  *
    01042  *  Passes each element of the collection to the given block. The method
    01043  *  returns <code>true</code> if the block never returns <code>true</code>
    01044  *  for all elements. If the block is not given, <code>none?</code> will return
    01045  *  <code>true</code> only if none of the collection members is true.
    01046  *
    01047  *     %w{ant bear cat}.none? {|word| word.length == 5}  #=> true
    01048  *     %w{ant bear cat}.none? {|word| word.length >= 4}  #=> false
    01049  *     [].none?                                          #=> true
    01050  *     [nil].none?                                       #=> true
    01051  *     [nil,false].none?                                 #=> true
    01052  */
    01053 static VALUE
    01054 enum_none(VALUE obj)
    01055 {
    01056     VALUE result = Qtrue;
    01057
    01058     rb_block_call(obj, id_each, 0, 0, ENUMFUNC(none), (VALUE)&result);
    01059     return result;
    01060 }
    01061
    01062 static VALUE
    01063 min_i(VALUE i, VALUE *memo, int argc, VALUE *argv)
    01064 {
    01065     VALUE cmp;
    01066
    01067     ENUM_WANT_SVALUE();
    01068
    01069     if (*memo == Qundef) {
    01070         *memo = i;
    01071     }
    01072     else {
    01073         cmp = rb_funcall(i, id_cmp, 1, *memo);
    01074         if (rb_cmpint(cmp, i, *memo) < 0) {
    01075             *memo = i;
    01076         }
    01077     }
    01078     return Qnil;
    01079 }
    01080
    01081 static VALUE
    01082 min_ii(VALUE i, VALUE *memo, int argc, VALUE *argv)
    01083 {
    01084     VALUE cmp;
    01085
    01086     ENUM_WANT_SVALUE();
    01087
    01088     if (*memo == Qundef) {
    01089         *memo = i;
    01090     }
    01091     else {
    01092         cmp = rb_yield_values(2, i, *memo);
    01093         if (rb_cmpint(cmp, i, *memo) < 0) {
    01094             *memo = i;
    01095         }
    01096     }
    01097     return Qnil;
    01098 }
    01099
    01100
    01101 /*
    01102  *  call-seq:
    01103  *     enum.min                    -> obj
    01104  *     enum.min {| a,b | block }   -> obj
    01105  *
    01106  *  Returns the object in <i>enum</i> with the minimum value. The
    01107  *  first form assumes all objects implement <code>Comparable</code>;
    01108  *  the second uses the block to return <em>a <=> b</em>.
    01109  *
    01110  *     a = %w(albatross dog horse)
    01111  *     a.min                                  #=> "albatross"
    01112  *     a.min {|a,b| a.length <=> b.length }   #=> "dog"
    01113  */
    01114
    01115 static VALUE
    01116 enum_min(VALUE obj)
    01117 {
    01118     VALUE result = Qundef;
    01119
    01120     if (rb_block_given_p()) {
    01121         rb_block_call(obj, id_each, 0, 0, min_ii, (VALUE)&result);
    01122     }
    01123     else {
    01124         rb_block_call(obj, id_each, 0, 0, min_i, (VALUE)&result);
    01125     }
    01126     if (result == Qundef) return Qnil;
    01127     return result;
    01128 }
    01129
    01130 static VALUE
    01131 max_i(VALUE i, VALUE *memo, int argc, VALUE *argv)
    01132 {
    01133     VALUE cmp;
    01134
    01135     ENUM_WANT_SVALUE();
    01136
    01137     if (*memo == Qundef) {
    01138         *memo = i;
    01139     }
    01140     else {
    01141         cmp = rb_funcall(i, id_cmp, 1, *memo);
    01142         if (rb_cmpint(cmp, i, *memo) > 0) {
    01143             *memo = i;
    01144         }
    01145     }
    01146     return Qnil;
    01147 }
    01148
    01149 static VALUE
    01150 max_ii(VALUE i, VALUE *memo, int argc, VALUE *argv)
    01151 {
    01152     VALUE cmp;
    01153
    01154     ENUM_WANT_SVALUE();
    01155
    01156     if (*memo == Qundef) {
    01157         *memo = i;
    01158     }
    01159     else {
    01160         cmp = rb_yield_values(2, i, *memo);
    01161         if (rb_cmpint(cmp, i, *memo) > 0) {
    01162             *memo = i;
    01163         }
    01164     }
    01165     return Qnil;
    01166 }
    01167
    01168 /*
    01169  *  call-seq:
    01170  *     enum.max                   -> obj
    01171  *     enum.max {|a,b| block }    -> obj
    01172  *
    01173  *  Returns the object in _enum_ with the maximum value. The
    01174  *  first form assumes all objects implement <code>Comparable</code>;
    01175  *  the second uses the block to return <em>a <=> b</em>.
    01176  *
    01177  *     a = %w(albatross dog horse)
    01178  *     a.max                                  #=> "horse"
    01179  *     a.max {|a,b| a.length <=> b.length }   #=> "albatross"
    01180  */
    01181
    01182 static VALUE
    01183 enum_max(VALUE obj)
    01184 {
    01185     VALUE result = Qundef;
    01186
    01187     if (rb_block_given_p()) {
    01188         rb_block_call(obj, id_each, 0, 0, max_ii, (VALUE)&result);
    01189     }
    01190     else {
    01191         rb_block_call(obj, id_each, 0, 0, max_i, (VALUE)&result);
    01192     }
    01193     if (result == Qundef) return Qnil;
    01194     return result;
    01195 }
    01196
    01197 struct minmax_t {
    01198     VALUE min;
    01199     VALUE max;
    01200     VALUE last;
    01201 };
    01202
    01203 static void
    01204 minmax_i_update(VALUE i, VALUE j, struct minmax_t *memo)
    01205 {
    01206     int n;
    01207
    01208     if (memo->min == Qundef) {
    01209         memo->min = i;
    01210         memo->max = j;
    01211     }
    01212     else {
    01213         n = rb_cmpint(rb_funcall(i, id_cmp, 1, memo->min), i, memo->min);
    01214         if (n < 0) {
    01215             memo->min = i;
    01216         }
    01217         n = rb_cmpint(rb_funcall(j, id_cmp, 1, memo->max), j, memo->max);
    01218         if (n > 0) {
    01219             memo->max = j;
    01220         }
    01221     }
    01222 }
    01223
    01224 static VALUE
    01225 minmax_i(VALUE i, VALUE _memo, int argc, VALUE *argv)
    01226 {
    01227     struct minmax_t *memo = (struct minmax_t *)_memo;
    01228     int n;
    01229     VALUE j;
    01230
    01231     ENUM_WANT_SVALUE();
    01232
    01233     if (memo->last == Qundef) {
    01234         memo->last = i;
    01235         return Qnil;
    01236     }
    01237     j = memo->last;
    01238     memo->last = Qundef;
    01239
    01240     n = rb_cmpint(rb_funcall(j, id_cmp, 1, i), j, i);
    01241     if (n == 0)
    01242         i = j;
    01243     else if (n < 0) {
    01244         VALUE tmp;
    01245         tmp = i;
    01246         i = j;
    01247         j = tmp;
    01248     }
    01249
    01250     minmax_i_update(i, j, memo);
    01251
    01252     return Qnil;
    01253 }
    01254
    01255 static void
    01256 minmax_ii_update(VALUE i, VALUE j, struct minmax_t *memo)
    01257 {
    01258     int n;
    01259
    01260     if (memo->min == Qundef) {
    01261         memo->min = i;
    01262         memo->max = j;
    01263     }
    01264     else {
    01265         n = rb_cmpint(rb_yield_values(2, i, memo->min), i, memo->min);
    01266         if (n < 0) {
    01267             memo->min = i;
    01268         }
    01269         n = rb_cmpint(rb_yield_values(2, j, memo->max), j, memo->max);
    01270         if (n > 0) {
    01271             memo->max = j;
    01272         }
    01273     }
    01274 }
    01275
    01276 static VALUE
    01277 minmax_ii(VALUE i, VALUE _memo, int argc, VALUE *argv)
    01278 {
    01279     struct minmax_t *memo = (struct minmax_t *)_memo;
    01280     int n;
    01281     VALUE j;
    01282
    01283     ENUM_WANT_SVALUE();
    01284
    01285     if (memo->last == Qundef) {
    01286         memo->last = i;
    01287         return Qnil;
    01288     }
    01289     j = memo->last;
    01290     memo->last = Qundef;
    01291
    01292     n = rb_cmpint(rb_yield_values(2, j, i), j, i);
    01293     if (n == 0)
    01294         i = j;
    01295     else if (n < 0) {
    01296         VALUE tmp;
    01297         tmp = i;
    01298         i = j;
    01299         j = tmp;
    01300     }
    01301
    01302     minmax_ii_update(i, j, memo);
    01303
    01304     return Qnil;
    01305 }
    01306
    01307 /*
    01308  *  call-seq:
    01309  *     enum.minmax                   -> [min,max]
    01310  *     enum.minmax {|a,b| block }    -> [min,max]
    01311  *
    01312  *  Returns two elements array which contains the minimum and the
    01313  *  maximum value in the enumerable.  The first form assumes all
    01314  *  objects implement <code>Comparable</code>; the second uses the
    01315  *  block to return <em>a <=> b</em>.
    01316  *
    01317  *     a = %w(albatross dog horse)
    01318  *     a.minmax                                  #=> ["albatross", "horse"]
    01319  *     a.minmax {|a,b| a.length <=> b.length }   #=> ["dog", "albatross"]
    01320  */
    01321
    01322 static VALUE
    01323 enum_minmax(VALUE obj)
    01324 {
    01325     struct minmax_t memo;
    01326     VALUE ary = rb_ary_new3(2, Qnil, Qnil);
    01327
    01328     memo.min = Qundef;
    01329     memo.last = Qundef;
    01330     if (rb_block_given_p()) {
    01331         rb_block_call(obj, id_each, 0, 0, minmax_ii, (VALUE)&memo);
    01332         if (memo.last != Qundef)
    01333             minmax_ii_update(memo.last, memo.last, &memo);
    01334     }
    01335     else {
    01336         rb_block_call(obj, id_each, 0, 0, minmax_i, (VALUE)&memo);
    01337         if (memo.last != Qundef)
    01338             minmax_i_update(memo.last, memo.last, &memo);
    01339     }
    01340     if (memo.min != Qundef) {
    01341         rb_ary_store(ary, 0, memo.min);
    01342         rb_ary_store(ary, 1, memo.max);
    01343     }
    01344     return ary;
    01345 }
    01346
    01347 static VALUE
    01348 min_by_i(VALUE i, VALUE *memo, int argc, VALUE *argv)
    01349 {
    01350     VALUE v;
    01351
    01352     ENUM_WANT_SVALUE();
    01353
    01354     v = rb_yield(i);
    01355     if (memo[0] == Qundef) {
    01356         memo[0] = v;
    01357         memo[1] = i;
    01358     }
    01359     else if (rb_cmpint(rb_funcall(v, id_cmp, 1, memo[0]), v, memo[0]) < 0) {
    01360         memo[0] = v;
    01361         memo[1] = i;
    01362     }
    01363     return Qnil;
    01364 }
    01365
    01366 /*
    01367  *  call-seq:
    01368  *     enum.min_by {|obj| block }   -> obj
    01369  *     enum.min_by                  -> an_enumerator
    01370  *
    01371  *  Returns the object in <i>enum</i> that gives the minimum
    01372  *  value from the given block.
    01373  *
    01374  *  If no block is given, an enumerator is returned instead.
    01375  *
    01376  *     a = %w(albatross dog horse)
    01377  *     a.min_by {|x| x.length }   #=> "dog"
    01378  */
    01379
    01380 static VALUE
    01381 enum_min_by(VALUE obj)
    01382 {
    01383     VALUE memo[2];
    01384
    01385     RETURN_ENUMERATOR(obj, 0, 0);
    01386
    01387     memo[0] = Qundef;
    01388     memo[1] = Qnil;
    01389     rb_block_call(obj, id_each, 0, 0, min_by_i, (VALUE)memo);
    01390     return memo[1];
    01391 }
    01392
    01393 static VALUE
    01394 max_by_i(VALUE i, VALUE *memo, int argc, VALUE *argv)
    01395 {
    01396     VALUE v;
    01397
    01398     ENUM_WANT_SVALUE();
    01399
    01400     v = rb_yield(i);
    01401     if (memo[0] == Qundef) {
    01402         memo[0] = v;
    01403         memo[1] = i;
    01404     }
    01405     else if (rb_cmpint(rb_funcall(v, id_cmp, 1, memo[0]), v, memo[0]) > 0) {
    01406         memo[0] = v;
    01407         memo[1] = i;
    01408     }
    01409     return Qnil;
    01410 }
    01411
    01412 /*
    01413  *  call-seq:
    01414  *     enum.max_by {|obj| block }   -> obj
    01415  *     enum.max_by                  -> an_enumerator
    01416  *
    01417  *  Returns the object in <i>enum</i> that gives the maximum
    01418  *  value from the given block.
    01419  *
    01420  *  If no block is given, an enumerator is returned instead.
    01421  *
    01422  *     a = %w(albatross dog horse)
    01423  *     a.max_by {|x| x.length }   #=> "albatross"
    01424  */
    01425
    01426 static VALUE
    01427 enum_max_by(VALUE obj)
    01428 {
    01429     VALUE memo[2];
    01430
    01431     RETURN_ENUMERATOR(obj, 0, 0);
    01432
    01433     memo[0] = Qundef;
    01434     memo[1] = Qnil;
    01435     rb_block_call(obj, id_each, 0, 0, max_by_i, (VALUE)memo);
    01436     return memo[1];
    01437 }
    01438
    01439 struct minmax_by_t {
    01440     VALUE min_bv;
    01441     VALUE max_bv;
    01442     VALUE min;
    01443     VALUE max;
    01444     VALUE last_bv;
    01445     VALUE last;
    01446 };
    01447
    01448 static void
    01449 minmax_by_i_update(VALUE v1, VALUE v2, VALUE i1, VALUE i2, struct minmax_by_t *memo)
    01450 {
    01451     if (memo->min_bv == Qundef) {
    01452         memo->min_bv = v1;
    01453         memo->max_bv = v2;
    01454         memo->min = i1;
    01455         memo->max = i2;
    01456     }
    01457     else {
    01458         if (rb_cmpint(rb_funcall(v1, id_cmp, 1, memo->min_bv), v1, memo->min_bv) < 0) {
    01459             memo->min_bv = v1;
    01460             memo->min = i1;
    01461         }
    01462         if (rb_cmpint(rb_funcall(v2, id_cmp, 1, memo->max_bv), v2, memo->max_bv) > 0) {
    01463             memo->max_bv = v2;
    01464             memo->max = i2;
    01465         }
    01466     }
    01467 }
    01468
    01469 static VALUE
    01470 minmax_by_i(VALUE i, VALUE _memo, int argc, VALUE *argv)
    01471 {
    01472     struct minmax_by_t *memo = (struct minmax_by_t *)_memo;
    01473     VALUE vi, vj, j;
    01474     int n;
    01475
    01476     ENUM_WANT_SVALUE();
    01477
    01478     vi = rb_yield(i);
    01479
    01480     if (memo->last_bv == Qundef) {
    01481         memo->last_bv = vi;
    01482         memo->last = i;
    01483         return Qnil;
    01484     }
    01485     vj = memo->last_bv;
    01486     j = memo->last;
    01487     memo->last_bv = Qundef;
    01488
    01489     n = rb_cmpint(rb_funcall(vj, id_cmp, 1, vi), vj, vi);
    01490     if (n == 0) {
    01491         i = j;
    01492         vi = vj;
    01493     }
    01494     else if (n < 0) {
    01495         VALUE tmp;
    01496         tmp = i;
    01497         i = j;
    01498         j = tmp;
    01499         tmp = vi;
    01500         vi = vj;
    01501         vj = tmp;
    01502     }
    01503
    01504     minmax_by_i_update(vi, vj, i, j, memo);
    01505
    01506     return Qnil;
    01507 }
    01508
    01509 /*
    01510  *  call-seq:
    01511  *     enum.minmax_by {|obj| block }   -> [min, max]
    01512  *     enum.minmax_by                  -> an_enumerator
    01513  *
    01514  *  Returns two elements array array containing the objects in
    01515  *  <i>enum</i> that gives the minimum and maximum values respectively
    01516  *  from the given block.
    01517  *
    01518  *  If no block is given, an enumerator is returned instead.
    01519  *
    01520  *     a = %w(albatross dog horse)
    01521  *     a.minmax_by {|x| x.length }   #=> ["dog", "albatross"]
    01522  */
    01523
    01524 static VALUE
    01525 enum_minmax_by(VALUE obj)
    01526 {
    01527     struct minmax_by_t memo;
    01528
    01529     RETURN_ENUMERATOR(obj, 0, 0);
    01530
    01531     memo.min_bv = Qundef;
    01532     memo.max_bv = Qundef;
    01533     memo.min = Qnil;
    01534     memo.max = Qnil;
    01535     memo.last_bv = Qundef;
    01536     memo.last = Qundef;
    01537     rb_block_call(obj, id_each, 0, 0, minmax_by_i, (VALUE)&memo);
    01538     if (memo.last_bv != Qundef)
    01539         minmax_by_i_update(memo.last_bv, memo.last_bv, memo.last, memo.last, &memo);
    01540     return rb_assoc_new(memo.min, memo.max);
    01541 }
    01542
    01543 static VALUE
    01544 member_i(VALUE iter, VALUE *memo, int argc, VALUE *argv)
    01545 {
    01546     if (rb_equal(enum_values_pack(argc, argv), memo[0])) {
    01547         memo[1] = Qtrue;
    01548         rb_iter_break();
    01549     }
    01550     return Qnil;
    01551 }
    01552
    01553 /*
    01554  *  call-seq:
    01555  *     enum.include?(obj)     -> true or false
    01556  *     enum.member?(obj)      -> true or false
    01557  *
    01558  *  Returns <code>true</code> if any member of <i>enum</i> equals
    01559  *  <i>obj</i>. Equality is tested using <code>==</code>.
    01560  *
    01561  *     IO.constants.include? :SEEK_SET          #=> true
    01562  *     IO.constants.include? :SEEK_NO_FURTHER   #=> false
    01563  *
    01564  */
    01565
    01566 static VALUE
    01567 enum_member(VALUE obj, VALUE val)
    01568 {
    01569     VALUE memo[2];
    01570
    01571     memo[0] = val;
    01572     memo[1] = Qfalse;
    01573     rb_block_call(obj, id_each, 0, 0, member_i, (VALUE)memo);
    01574     return memo[1];
    01575 }
    01576
    01577 static VALUE
    01578 each_with_index_i(VALUE i, VALUE memo, int argc, VALUE *argv)
    01579 {
    01580     long n = (*(VALUE *)memo)++;
    01581
    01582     return rb_yield_values(2, enum_values_pack(argc, argv), INT2NUM(n));
    01583 }
    01584
    01585 /*
    01586  *  call-seq:
    01587  *     enum.each_with_index(*args) {|obj, i| block }   ->  enum
    01588  *     enum.each_with_index(*args)                     ->  an_enumerator
    01589  *
    01590  *  Calls <em>block</em> with two arguments, the item and its index,
    01591  *  for each item in <i>enum</i>.  Given arguments are passed through
    01592  *  to #each().
    01593  *
    01594  *  If no block is given, an enumerator is returned instead.
    01595  *
    01596  *     hash = Hash.new
    01597  *     %w(cat dog wombat).each_with_index {|item, index|
    01598  *       hash[item] = index
    01599  *     }
    01600  *     hash   #=> {"cat"=>0, "dog"=>1, "wombat"=>2}
    01601  *
    01602  */
    01603
    01604 static VALUE
    01605 enum_each_with_index(int argc, VALUE *argv, VALUE obj)
    01606 {
    01607     long memo;
    01608
    01609     RETURN_ENUMERATOR(obj, argc, argv);
    01610
    01611     memo = 0;
    01612     rb_block_call(obj, id_each, argc, argv, each_with_index_i, (VALUE)&memo);
    01613     return obj;
    01614 }
    01615
    01616
    01617 /*
    01618  *  call-seq:
    01619  *     enum.reverse_each(*args) {|item| block }   ->  enum
    01620  *     enum.reverse_each(*args)                   ->  an_enumerator
    01621  *
    01622  *  Builds a temporary array and traverses that array in reverse order.
    01623  *
    01624  *  If no block is given, an enumerator is returned instead.
    01625  *
    01626  */
    01627
    01628 static VALUE
    01629 enum_reverse_each(int argc, VALUE *argv, VALUE obj)
    01630 {
    01631     VALUE ary;
    01632     long i;
    01633
    01634     RETURN_ENUMERATOR(obj, argc, argv);
    01635
    01636     ary = enum_to_a(argc, argv, obj);
    01637
    01638     for (i = RARRAY_LEN(ary); --i >= 0; ) {
    01639         rb_yield(RARRAY_PTR(ary)[i]);
    01640     }
    01641
    01642     return obj;
    01643 }
    01644
    01645
    01646 static VALUE
    01647 each_val_i(VALUE i, VALUE p, int argc, VALUE *argv)
    01648 {
    01649     ENUM_WANT_SVALUE();
    01650     rb_yield(i);
    01651     return Qnil;
    01652 }
    01653
    01654 /*
    01655  *  call-seq:
    01656  *     enum.each_entry {|obj| block}  -> enum
    01657  *     enum.each_entry                -> an_enumerator
    01658  *
    01659  *  Calls <i>block</i> once for each element in +self+, passing that
    01660  *  element as a parameter, converting multiple values from yield to an
    01661  *  array.
    01662  *
    01663  *  If no block is given, an enumerator is returned instead.
    01664  *
    01665  *     class Foo
    01666  *       include Enumerable
    01667  *       def each
    01668  *         yield 1
    01669  *         yield 1,2
    01670  *       end
    01671  *     end
    01672  *     Foo.new.each_entry{|o| print o, " -- "}
    01673  *
    01674  *  produces:
    01675  *
    01676  *     1 -- [1, 2] --
    01677  */
    01678
    01679 static VALUE
    01680 enum_each_entry(int argc, VALUE *argv, VALUE obj)
    01681 {
    01682     RETURN_ENUMERATOR(obj, argc, argv);
    01683     rb_block_call(obj, id_each, argc, argv, each_val_i, 0);
    01684     return obj;
    01685 }
    01686
    01687 static VALUE
    01688 each_slice_i(VALUE i, VALUE *memo, int argc, VALUE *argv)
    01689 {
    01690     VALUE ary = memo[0];
    01691     VALUE v = Qnil;
    01692     long size = (long)memo[1];
    01693     ENUM_WANT_SVALUE();
    01694
    01695     rb_ary_push(ary, i);
    01696
    01697     if (RARRAY_LEN(ary) == size) {
    01698         v = rb_yield(ary);
    01699         memo[0] = rb_ary_new2(size);
    01700     }
    01701
    01702     return v;
    01703 }
    01704
    01705 /*
    01706  *  call-seq:
    01707  *    enum.each_slice(n) {...}  ->  nil
    01708  *    enum.each_slice(n)        ->  an_enumerator
    01709  *
    01710  *  Iterates the given block for each slice of <n> elements.  If no
    01711  *  block is given, returns an enumerator.
    01712  *
    01713  *  e.g.:
    01714  *      (1..10).each_slice(3) {|a| p a}
    01715  *      # outputs below
    01716  *      [1, 2, 3]
    01717  *      [4, 5, 6]
    01718  *      [7, 8, 9]
    01719  *      [10]
    01720  *
    01721  */
    01722 static VALUE
    01723 enum_each_slice(VALUE obj, VALUE n)
    01724 {
    01725     long size = NUM2LONG(n);
    01726     VALUE args[2], ary;
    01727
    01728     if (size <= 0) rb_raise(rb_eArgError, "invalid slice size");
    01729     RETURN_ENUMERATOR(obj, 1, &n);
    01730     args[0] = rb_ary_new2(size);
    01731     args[1] = (VALUE)size;
    01732
    01733     rb_block_call(obj, id_each, 0, 0, each_slice_i, (VALUE)args);
    01734
    01735     ary = args[0];
    01736     if (RARRAY_LEN(ary) > 0) rb_yield(ary);
    01737
    01738     return Qnil;
    01739 }
    01740
    01741 static VALUE
    01742 each_cons_i(VALUE i, VALUE *memo, int argc, VALUE *argv)
    01743 {
    01744     VALUE ary = memo[0];
    01745     VALUE v = Qnil;
    01746     long size = (long)memo[1];
    01747     ENUM_WANT_SVALUE();
    01748
    01749     if (RARRAY_LEN(ary) == size) {
    01750         rb_ary_shift(ary);
    01751     }
    01752     rb_ary_push(ary, i);
    01753     if (RARRAY_LEN(ary) == size) {
    01754         v = rb_yield(rb_ary_dup(ary));
    01755     }
    01756     return v;
    01757 }
    01758
    01759 /*
    01760  *  call-seq:
    01761  *    enum.each_cons(n) {...}   ->  nil
    01762  *    enum.each_cons(n)         ->  an_enumerator
    01763  *
    01764  *  Iterates the given block for each array of consecutive <n>
    01765  *  elements.  If no block is given, returns an enumerator.
    01766  *
    01767  *  e.g.:
    01768  *      (1..10).each_cons(3) {|a| p a}
    01769  *      # outputs below
    01770  *      [1, 2, 3]
    01771  *      [2, 3, 4]
    01772  *      [3, 4, 5]
    01773  *      [4, 5, 6]
    01774  *      [5, 6, 7]
    01775  *      [6, 7, 8]
    01776  *      [7, 8, 9]
    01777  *      [8, 9, 10]
    01778  *
    01779  */
    01780 static VALUE
    01781 enum_each_cons(VALUE obj, VALUE n)
    01782 {
    01783     long size = NUM2LONG(n);
    01784     VALUE args[2];
    01785
    01786     if (size <= 0) rb_raise(rb_eArgError, "invalid size");
    01787     RETURN_ENUMERATOR(obj, 1, &n);
    01788     args[0] = rb_ary_new2(size);
    01789     args[1] = (VALUE)size;
    01790
    01791     rb_block_call(obj, id_each, 0, 0, each_cons_i, (VALUE)args);
    01792
    01793     return Qnil;
    01794 }
    01795
    01796 static VALUE
    01797 each_with_object_i(VALUE i, VALUE memo, int argc, VALUE *argv)
    01798 {
    01799     ENUM_WANT_SVALUE();
    01800     return rb_yield_values(2, i, memo);
    01801 }
    01802
    01803 /*
    01804  *  call-seq:
    01805  *    enum.each_with_object(obj) {|(*args), memo_obj| ... }  ->  obj
    01806  *    enum.each_with_object(obj)                             ->  an_enumerator
    01807  *
    01808  *  Iterates the given block for each element with an arbitrary
    01809  *  object given, and returns the initially given object.
    01810  *
    01811  *  If no block is given, returns an enumerator.
    01812  *
    01813  *  e.g.:
    01814  *      evens = (1..10).each_with_object([]) {|i, a| a << i*2 }
    01815  *      #=> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
    01816  *
    01817  */
    01818 static VALUE
    01819 enum_each_with_object(VALUE obj, VALUE memo)
    01820 {
    01821     RETURN_ENUMERATOR(obj, 1, &memo);
    01822
    01823     rb_block_call(obj, id_each, 0, 0, each_with_object_i, memo);
    01824
    01825     return memo;
    01826 }
    01827
    01828 static VALUE
    01829 zip_ary(VALUE val, NODE *memo, int argc, VALUE *argv)
    01830 {
    01831     volatile VALUE result = memo->u1.value;
    01832     volatile VALUE args = memo->u2.value;
    01833     long n = memo->u3.cnt++;
    01834     volatile VALUE tmp;
    01835     int i;
    01836
    01837     tmp = rb_ary_new2(RARRAY_LEN(args) + 1);
    01838     rb_ary_store(tmp, 0, enum_values_pack(argc, argv));
    01839     for (i=0; i<RARRAY_LEN(args); i++) {
    01840         VALUE e = RARRAY_PTR(args)[i];
    01841
    01842         if (RARRAY_LEN(e) <= n) {
    01843             rb_ary_push(tmp, Qnil);
    01844         }
    01845         else {
    01846             rb_ary_push(tmp, RARRAY_PTR(e)[n]);
    01847         }
    01848     }
    01849     if (NIL_P(result)) {
    01850         rb_yield(tmp);
    01851     }
    01852     else {
    01853         rb_ary_push(result, tmp);
    01854     }
    01855     return Qnil;
    01856 }
    01857
    01858 static VALUE
    01859 call_next(VALUE *v)
    01860 {
    01861     return v[0] = rb_funcall(v[1], id_next, 0, 0);
    01862 }
    01863
    01864 static VALUE
    01865 call_stop(VALUE *v)
    01866 {
    01867     return v[0] = Qundef;
    01868 }
    01869
    01870 static VALUE
    01871 zip_i(VALUE val, NODE *memo, int argc, VALUE *argv)
    01872 {
    01873     volatile VALUE result = memo->u1.value;
    01874     volatile VALUE args = memo->u2.value;
    01875     volatile VALUE tmp;
    01876     int i;
    01877
    01878     tmp = rb_ary_new2(RARRAY_LEN(args) + 1);
    01879     rb_ary_store(tmp, 0, enum_values_pack(argc, argv));
    01880     for (i=0; i<RARRAY_LEN(args); i++) {
    01881         if (NIL_P(RARRAY_PTR(args)[i])) {
    01882             rb_ary_push(tmp, Qnil);
    01883         }
    01884         else {
    01885             VALUE v[2];
    01886
    01887             v[1] = RARRAY_PTR(args)[i];
    01888             rb_rescue2(call_next, (VALUE)v, call_stop, (VALUE)v, rb_eStopIteration, 0);
    01889             if (v[0] == Qundef) {
    01890                 RARRAY_PTR(args)[i] = Qnil;
    01891                 v[0] = Qnil;
    01892             }
    01893             rb_ary_push(tmp, v[0]);
    01894         }
    01895     }
    01896     if (NIL_P(result)) {
    01897         rb_yield(tmp);
    01898     }
    01899     else {
    01900         rb_ary_push(result, tmp);
    01901     }
    01902     return Qnil;
    01903 }
    01904
    01905 /*
    01906  *  call-seq:
    01907  *     enum.zip(arg, ...)                   -> an_array_of_array
    01908  *     enum.zip(arg, ...) {|arr| block }    -> nil
    01909  *
    01910  *  Takes one element from <i>enum</i> and merges corresponding
    01911  *  elements from each <i>args</i>.  This generates a sequence of
    01912  *  <em>n</em>-element arrays, where <em>n</em> is one more than the
    01913  *  count of arguments.  The length of the resulting sequence will be
    01914  *  <code>enum#size</code>.  If the size of any argument is less than
    01915  *  <code>enum#size</code>, <code>nil</code> values are supplied. If
    01916  *  a block is given, it is invoked for each output array, otherwise
    01917  *  an array of arrays is returned.
    01918  *
    01919  *     a = [ 4, 5, 6 ]
    01920  *     b = [ 7, 8, 9 ]
    01921  *
    01922  *     [1,2,3].zip(a, b)      #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
    01923  *     [1,2].zip(a,b)         #=> [[1, 4, 7], [2, 5, 8]]
    01924  *     a.zip([1,2],[8])       #=> [[4, 1, 8], [5, 2, nil], [6, nil, nil]]
    01925  *
    01926  */
    01927
    01928 static VALUE
    01929 enum_zip(int argc, VALUE *argv, VALUE obj)
    01930 {
    01931     int i;
    01932     ID conv;
    01933     NODE *memo;
    01934     VALUE result = Qnil;
    01935     VALUE args = rb_ary_new4(argc, argv);
    01936     int allary = TRUE;
    01937
    01938     argv = RARRAY_PTR(args);
    01939     for (i=0; i<argc; i++) {
    01940         VALUE ary = rb_check_array_type(argv[i]);
    01941         if (NIL_P(ary)) {
    01942             allary = FALSE;
    01943             break;
    01944         }
    01945         argv[i] = ary;
    01946     }
    01947     if (!allary) {
    01948         CONST_ID(conv, "to_enum");
    01949         for (i=0; i<argc; i++) {
    01950             argv[i] = rb_funcall(argv[i], conv, 1, ID2SYM(id_each));
    01951         }
    01952     }
    01953     if (!rb_block_given_p()) {
    01954         result = rb_ary_new();
    01955     }
    01956     /* use NODE_DOT2 as memo(v, v, -) */
    01957     memo = rb_node_newnode(NODE_DOT2, result, args, 0);
    01958     rb_block_call(obj, id_each, 0, 0, allary ? zip_ary : zip_i, (VALUE)memo);
    01959
    01960     return result;
    01961 }
    01962
    01963 static VALUE
    01964 take_i(VALUE i, VALUE *arg, int argc, VALUE *argv)
    01965 {
    01966     rb_ary_push(arg[0], enum_values_pack(argc, argv));
    01967     if (--arg[1] == 0) rb_iter_break();
    01968     return Qnil;
    01969 }
    01970
    01971 /*
    01972  *  call-seq:
    01973  *     enum.take(n)               -> array
    01974  *
    01975  *  Returns first n elements from <i>enum</i>.
    01976  *
    01977  *     a = [1, 2, 3, 4, 5, 0]
    01978  *     a.take(3)             #=> [1, 2, 3]
    01979  *
    01980  */
    01981
    01982 static VALUE
    01983 enum_take(VALUE obj, VALUE n)
    01984 {
    01985     VALUE args[2];
    01986     long len = NUM2LONG(n);
    01987
    01988     if (len < 0) {
    01989         rb_raise(rb_eArgError, "attempt to take negative size");
    01990     }
    01991
    01992     if (len == 0) return rb_ary_new2(0);
    01993     args[0] = rb_ary_new();
    01994     args[1] = len;
    01995     rb_block_call(obj, id_each, 0, 0, take_i, (VALUE)args);
    01996     return args[0];
    01997 }
    01998
    01999
    02000 static VALUE
    02001 take_while_i(VALUE i, VALUE *ary, int argc, VALUE *argv)
    02002 {
    02003     if (!RTEST(enum_yield(argc, argv))) rb_iter_break();
    02004     rb_ary_push(*ary, enum_values_pack(argc, argv));
    02005     return Qnil;
    02006 }
    02007
    02008 /*
    02009  *  call-seq:
    02010  *     enum.take_while {|arr| block }   -> array
    02011  *     enum.take_while                  -> an_enumerator
    02012  *
    02013  *  Passes elements to the block until the block returns +nil+ or +false+,
    02014  *  then stops iterating and returns an array of all prior elements.
    02015  *
    02016  *  If no block is given, an enumerator is returned instead.
    02017  *
    02018  *     a = [1, 2, 3, 4, 5, 0]
    02019  *     a.take_while {|i| i < 3 }   #=> [1, 2]
    02020  *
    02021  */
    02022
    02023 static VALUE
    02024 enum_take_while(VALUE obj)
    02025 {
    02026     VALUE ary;
    02027
    02028     RETURN_ENUMERATOR(obj, 0, 0);
    02029     ary = rb_ary_new();
    02030     rb_block_call(obj, id_each, 0, 0, take_while_i, (VALUE)&ary);
    02031     return ary;
    02032 }
    02033
    02034 static VALUE
    02035 drop_i(VALUE i, VALUE *arg, int argc, VALUE *argv)
    02036 {
    02037     if (arg[1] == 0) {
    02038         rb_ary_push(arg[0], enum_values_pack(argc, argv));
    02039     }
    02040     else {
    02041         arg[1]--;
    02042     }
    02043     return Qnil;
    02044 }
    02045
    02046 /*
    02047  *  call-seq:
    02048  *     enum.drop(n)               -> array
    02049  *
    02050  *  Drops first n elements from <i>enum</i>, and returns rest elements
    02051  *  in an array.
    02052  *
    02053  *     a = [1, 2, 3, 4, 5, 0]
    02054  *     a.drop(3)             #=> [4, 5, 0]
    02055  *
    02056  */
    02057
    02058 static VALUE
    02059 enum_drop(VALUE obj, VALUE n)
    02060 {
    02061     VALUE args[2];
    02062     long len = NUM2LONG(n);
    02063
    02064     if (len < 0) {
    02065         rb_raise(rb_eArgError, "attempt to drop negative size");
    02066     }
    02067
    02068     args[1] = len;
    02069     args[0] = rb_ary_new();
    02070     rb_block_call(obj, id_each, 0, 0, drop_i, (VALUE)args);
    02071     return args[0];
    02072 }
    02073
    02074
    02075 static VALUE
    02076 drop_while_i(VALUE i, VALUE *args, int argc, VALUE *argv)
    02077 {
    02078     ENUM_WANT_SVALUE();
    02079
    02080     if (!args[1] && !RTEST(rb_yield(i))) {
    02081         args[1] = Qtrue;
    02082     }
    02083     if (args[1]) {
    02084         rb_ary_push(args[0], i);
    02085     }
    02086     return Qnil;
    02087 }
    02088
    02089 /*
    02090  *  call-seq:
    02091  *     enum.drop_while {|arr| block }   -> array
    02092  *     enum.drop_while                  -> an_enumerator
    02093  *
    02094  *  Drops elements up to, but not including, the first element for
    02095  *  which the block returns +nil+ or +false+ and returns an array
    02096  *  containing the remaining elements.
    02097  *
    02098  *  If no block is given, an enumerator is returned instead.
    02099  *
    02100  *     a = [1, 2, 3, 4, 5, 0]
    02101  *     a.drop_while {|i| i < 3 }   #=> [3, 4, 5, 0]
    02102  *
    02103  */
    02104
    02105 static VALUE
    02106 enum_drop_while(VALUE obj)
    02107 {
    02108     VALUE args[2];
    02109
    02110     RETURN_ENUMERATOR(obj, 0, 0);
    02111     args[0] = rb_ary_new();
    02112     args[1] = Qfalse;
    02113     rb_block_call(obj, id_each, 0, 0, drop_while_i, (VALUE)args);
    02114     return args[0];
    02115 }
    02116
    02117 static VALUE
    02118 cycle_i(VALUE i, VALUE ary, int argc, VALUE *argv)
    02119 {
    02120     ENUM_WANT_SVALUE();
    02121
    02122     rb_ary_push(ary, i);
    02123     rb_yield(i);
    02124     return Qnil;
    02125 }
    02126
    02127 /*
    02128  *  call-seq:
    02129  *     enum.cycle(n=nil) {|obj| block }   ->  nil
    02130  *     enum.cycle(n=nil)                  ->  an_enumerator
    02131  *
    02132  *  Calls <i>block</i> for each element of <i>enum</i> repeatedly _n_
    02133  *  times or forever if none or +nil+ is given.  If a non-positive
    02134  *  number is given or the collection is empty, does nothing.  Returns
    02135  *  +nil+ if the loop has finished without getting interrupted.
    02136  *
    02137  *  Enumerable#cycle saves elements in an internal array so changes
    02138  *  to <i>enum</i> after the first pass have no effect.
    02139  *
    02140  *  If no block is given, an enumerator is returned instead.
    02141  *
    02142  *     a = ["a", "b", "c"]
    02143  *     a.cycle {|x| puts x }  # print, a, b, c, a, b, c,.. forever.
    02144  *     a.cycle(2) {|x| puts x }  # print, a, b, c, a, b, c.
    02145  *
    02146  */
    02147
    02148 static VALUE
    02149 enum_cycle(int argc, VALUE *argv, VALUE obj)
    02150 {
    02151     VALUE ary;
    02152     VALUE nv = Qnil;
    02153     long n, i, len;
    02154
    02155     rb_scan_args(argc, argv, "01", &nv);
    02156
    02157     RETURN_ENUMERATOR(obj, argc, argv);
    02158     if (NIL_P(nv)) {
    02159         n = -1;
    02160     }
    02161     else {
    02162         n = NUM2LONG(nv);
    02163         if (n <= 0) return Qnil;
    02164     }
    02165     ary = rb_ary_new();
    02166     RBASIC(ary)->klass = 0;
    02167     rb_block_call(obj, id_each, 0, 0, cycle_i, ary);
    02168     len = RARRAY_LEN(ary);
    02169     if (len == 0) return Qnil;
    02170     while (n < 0 || 0 < --n) {
    02171         for (i=0; i<len; i++) {
    02172             rb_yield(RARRAY_PTR(ary)[i]);
    02173         }
    02174     }
    02175     return Qnil;
    02176 }
    02177
    02178 struct chunk_arg {
    02179     VALUE categorize;
    02180     VALUE state;
    02181     VALUE prev_value;
    02182     VALUE prev_elts;
    02183     VALUE yielder;
    02184 };
    02185
    02186 static VALUE
    02187 chunk_ii(VALUE i, VALUE _argp, int argc, VALUE *argv)
    02188 {
    02189     struct chunk_arg *argp = (struct chunk_arg *)_argp;
    02190     VALUE v;
    02191     VALUE alone = ID2SYM(rb_intern("_alone"));
    02192     VALUE separator = ID2SYM(rb_intern("_separator"));
    02193
    02194     ENUM_WANT_SVALUE();
    02195
    02196     if (NIL_P(argp->state))
    02197         v = rb_funcall(argp->categorize, rb_intern("call"), 1, i);
    02198     else
    02199         v = rb_funcall(argp->categorize, rb_intern("call"), 2, i, argp->state);
    02200
    02201     if (v == alone) {
    02202         if (!NIL_P(argp->prev_value)) {
    02203             rb_funcall(argp->yielder, rb_intern("<<"), 1, rb_assoc_new(argp->prev_value, argp->prev_elts));
    02204             argp->prev_value = argp->prev_elts = Qnil;
    02205         }
    02206         rb_funcall(argp->yielder, rb_intern("<<"), 1, rb_assoc_new(v, rb_ary_new3(1, i)));
    02207     }
    02208     else if (NIL_P(v) || v == separator) {
    02209         if (!NIL_P(argp->prev_value)) {
    02210             rb_funcall(argp->yielder, rb_intern("<<"), 1, rb_assoc_new(argp->prev_value, argp->prev_elts));
    02211             argp->prev_value = argp->prev_elts = Qnil;
    02212         }
    02213     }
    02214     else if (SYMBOL_P(v) && rb_id2name(SYM2ID(v))[0] == '_') {
    02215         rb_raise(rb_eRuntimeError, "symbol begins with an underscore is reserved");
    02216     }
    02217     else {
    02218         if (NIL_P(argp->prev_value)) {
    02219             argp->prev_value = v;
    02220             argp->prev_elts = rb_ary_new3(1, i);
    02221         }
    02222         else {
    02223             if (rb_equal(argp->prev_value, v)) {
    02224                 rb_ary_push(argp->prev_elts, i);
    02225             }
    02226             else {
    02227                 rb_funcall(argp->yielder, rb_intern("<<"), 1, rb_assoc_new(argp->prev_value, argp->prev_elts));
    02228                 argp->prev_value = v;
    02229                 argp->prev_elts = rb_ary_new3(1, i);
    02230             }
    02231         }
    02232     }
    02233     return Qnil;
    02234 }
    02235
    02236 static VALUE
    02237 chunk_i(VALUE yielder, VALUE enumerator, int argc, VALUE *argv)
    02238 {
    02239     VALUE enumerable;
    02240     struct chunk_arg arg;
    02241
    02242     enumerable = rb_ivar_get(enumerator, rb_intern("chunk_enumerable"));
    02243     arg.categorize = rb_ivar_get(enumerator, rb_intern("chunk_categorize"));
    02244     arg.state = rb_ivar_get(enumerator, rb_intern("chunk_initial_state"));
    02245     arg.prev_value = Qnil;
    02246     arg.prev_elts = Qnil;
    02247     arg.yielder = yielder;
    02248
    02249     if (!NIL_P(arg.state))
    02250         arg.state = rb_obj_dup(arg.state);
    02251
    02252     rb_block_call(enumerable, id_each, 0, 0, chunk_ii, (VALUE)&arg);
    02253     if (!NIL_P(arg.prev_elts))
    02254         rb_funcall(arg.yielder, rb_intern("<<"), 1, rb_assoc_new(arg.prev_value, arg.prev_elts));
    02255     return Qnil;
    02256 }
    02257
    02258 /*
    02259  *  call-seq:
    02260  *     enum.chunk {|elt| ... }                       -> an_enumerator
    02261  *     enum.chunk(initial_state) {|elt, state| ... } -> an_enumerator
    02262  *
    02263  *  Creates an enumerator for each chunked elements.
    02264  *  The consecutive elements which have same block value are chunked.
    02265  *
    02266  *  The result enumerator yields the block value and an array of chunked elements.
    02267  *  So "each" method can be called as follows.
    02268  *
    02269  *    enum.chunk {|elt| key }.each {|key, ary| ... }
    02270  *    enum.chunk(initial_state) {|elt, state| key }.each {|key, ary| ... }
    02271  *
    02272  *  For example, consecutive even numbers and odd numbers can be
    02273  *  splitted as follows.
    02274  *
    02275  *    [3,1,4,1,5,9,2,6,5,3,5].chunk {|n|
    02276  *      n.even?
    02277  *    }.each {|even, ary|
    02278  *      p [even, ary]
    02279  *    }
    02280  *    #=> [false, [3, 1]]
    02281  *    #   [true, [4]]
    02282  *    #   [false, [1, 5, 9]]
    02283  *    #   [true, [2, 6]]
    02284  *    #   [false, [5, 3, 5]]
    02285  *
    02286  *  This method is especially useful for sorted series of elements.
    02287  *  The following example counts words for each initial letter.
    02288  *
    02289  *    open("/usr/share/dict/words", "r:iso-8859-1") {|f|
    02290  *      f.chunk {|line| line.ord }.each {|ch, lines| p [ch.chr, lines.length] }
    02291  *    }
    02292  *    #=> ["\n", 1]
    02293  *    #   ["A", 1327]
    02294  *    #   ["B", 1372]
    02295  *    #   ["C", 1507]
    02296  *    #   ["D", 791]
    02297  *    #   ...
    02298  *
    02299  *  The following key values has special meaning:
    02300  *  - nil and :_separator specifies that the elements are dropped.
    02301  *  - :_alone specifies that the element should be chunked as a singleton.
    02302  *  Other symbols which begins an underscore are reserved.
    02303  *
    02304  *  nil and :_separator can be used to ignore some elements.
    02305  *  For example, the sequence of hyphens in svn log can be eliminated as follows.
    02306  *
    02307  *    sep = "-"*72 + "\n"
    02308  *    IO.popen("svn log README") {|f|
    02309  *      f.chunk {|line|
    02310  *        line != sep || nil
    02311  *      }.each {|_, lines|
    02312  *        pp lines
    02313  *      }
    02314  *    }
    02315  *    #=> ["r20018 | knu | 2008-10-29 13:20:42 +0900 (Wed, 29 Oct 2008) | 2 lines\n",
    02316  *    #    "\n",
    02317  *    #    "* README, README.ja: Update the portability section.\n",
    02318  *    #    "\n"]
    02319  *    #   ["r16725 | knu | 2008-05-31 23:34:23 +0900 (Sat, 31 May 2008) | 2 lines\n",
    02320  *    #    "\n",
    02321  *    #    "* README, README.ja: Add a note about default C flags.\n",
    02322  *    #    "\n"]
    02323  *    #   ...
    02324  *
    02325  *  paragraphs separated by empty lines can be parsed as follows.
    02326  *
    02327  *    File.foreach("README").chunk {|line|
    02328  *      /\A\s*\z/ !~ line || nil
    02329  *    }.each {|_, lines|
    02330  *      pp lines
    02331  *    }
    02332  *
    02333  *  :_alone can be used to pass through bunch of elements.
    02334  *  For example, sort consecutive lines formed as Foo#bar and
    02335  *  pass other lines, chunk can be used as follows.
    02336  *
    02337  *    pat = /\A[A-Z][A-Za-z0-9_]+\#/
    02338  *    open(filename) {|f|
    02339  *      f.chunk {|line| pat =~ line ? $& : :_alone }.each {|key, lines|
    02340  *        if key != :_alone
    02341  *          print lines.sort.join('')
    02342  *        else
    02343  *          print lines.join('')
    02344  *        end
    02345  *      }
    02346  *    }
    02347  *
    02348  *  If the block needs to maintain state over multiple elements,
    02349  *  _initial_state_ argument can be used.
    02350  *  If non-nil value is given,
    02351  *  it is duplicated for each "each" method invocation of the enumerator.
    02352  *  The duplicated object is passed to 2nd argument of the block for "chunk" method.
    02353  *
    02354  */
    02355 static VALUE
    02356 enum_chunk(int argc, VALUE *argv, VALUE enumerable)
    02357 {
    02358     VALUE initial_state;
    02359     VALUE enumerator;
    02360
    02361     if(!rb_block_given_p())
    02362         rb_raise(rb_eArgError, "no block given");
    02363     rb_scan_args(argc, argv, "01", &initial_state);
    02364
    02365     enumerator = rb_obj_alloc(rb_cEnumerator);
    02366     rb_ivar_set(enumerator, rb_intern("chunk_enumerable"), enumerable);
    02367     rb_ivar_set(enumerator, rb_intern("chunk_categorize"), rb_block_proc());
    02368     rb_ivar_set(enumerator, rb_intern("chunk_initial_state"), initial_state);
    02369     rb_block_call(enumerator, rb_intern("initialize"), 0, 0, chunk_i, enumerator);
    02370     return enumerator;
    02371 }
    02372
    02373
    02374 struct slicebefore_arg {
    02375     VALUE sep_pred;
    02376     VALUE sep_pat;
    02377     VALUE state;
    02378     VALUE prev_elts;
    02379     VALUE yielder;
    02380 };
    02381
    02382 static VALUE
    02383 slicebefore_ii(VALUE i, VALUE _argp, int argc, VALUE *argv)
    02384 {
    02385     struct slicebefore_arg *argp = (struct slicebefore_arg *)_argp;
    02386     VALUE header_p;
    02387
    02388     ENUM_WANT_SVALUE();
    02389
    02390     if (!NIL_P(argp->sep_pat))
    02391         header_p = rb_funcall(argp->sep_pat, id_eqq, 1, i);
    02392     else if (NIL_P(argp->state))
    02393         header_p = rb_funcall(argp->sep_pred, rb_intern("call"), 1, i);
    02394     else
    02395         header_p = rb_funcall(argp->sep_pred, rb_intern("call"), 2, i, argp->state);
    02396     if (RTEST(header_p)) {
    02397         if (!NIL_P(argp->prev_elts))
    02398             rb_funcall(argp->yielder, rb_intern("<<"), 1, argp->prev_elts);
    02399         argp->prev_elts = rb_ary_new3(1, i);
    02400     }
    02401     else {
    02402         if (NIL_P(argp->prev_elts))
    02403             argp->prev_elts = rb_ary_new3(1, i);
    02404         else
    02405             rb_ary_push(argp->prev_elts, i);
    02406     }
    02407
    02408     return Qnil;
    02409 }
    02410
    02411 static VALUE
    02412 slicebefore_i(VALUE yielder, VALUE enumerator, int argc, VALUE *argv)
    02413 {
    02414     VALUE enumerable;
    02415     struct slicebefore_arg arg;
    02416
    02417     enumerable = rb_ivar_get(enumerator, rb_intern("slicebefore_enumerable"));
    02418     arg.sep_pred = rb_attr_get(enumerator, rb_intern("slicebefore_sep_pred"));
    02419     arg.sep_pat = NIL_P(arg.sep_pred) ? rb_ivar_get(enumerator, rb_intern("slicebefore_sep_pat")) : Qnil;
    02420     arg.state = rb_ivar_get(enumerator, rb_intern("slicebefore_initial_state"));
    02421     arg.prev_elts = Qnil;
    02422     arg.yielder = yielder;
    02423
    02424     if (!NIL_P(arg.state))
    02425         arg.state = rb_obj_dup(arg.state);
    02426
    02427     rb_block_call(enumerable, id_each, 0, 0, slicebefore_ii, (VALUE)&arg);
    02428     if (!NIL_P(arg.prev_elts))
    02429         rb_funcall(arg.yielder, rb_intern("<<"), 1, arg.prev_elts);
    02430     return Qnil;
    02431 }
    02432
    02433 /*
    02434  *  call-seq:
    02435  *     enum.slice_before(pattern)                            -> an_enumerator
    02436  *     enum.slice_before {|elt| bool }                       -> an_enumerator
    02437  *     enum.slice_before(initial_state) {|elt, state| bool } -> an_enumerator
    02438  *
    02439  *  Creates an enumerator for each chunked elements.
    02440  *  The beginnings of chunks are defined by _pattern_ and the block.
    02441  *  If _pattern_ === _elt_ returns true or
    02442  *  the block returns true for the element,
    02443  *  the element is beginning of a chunk.
    02444  *
    02445  *  The === and block is called from the first element to the last element
    02446  *  of _enum_.
    02447  *  The result for the first element is ignored.
    02448  *
    02449  *  The result enumerator yields the chunked elements as an array for +each+
    02450  *  method.
    02451  *  +each+ method can be called as follows.
    02452  *
    02453  *    enum.slice_before(pattern).each {|ary| ... }
    02454  *    enum.slice_before {|elt| bool }.each {|ary| ... }
    02455  *    enum.slice_before(initial_state) {|elt, state| bool }.each {|ary| ... }
    02456  *
    02457  *  Other methods of Enumerator class and Enumerable module,
    02458  *  such as map, etc., are also usable.
    02459  *
    02460  *  For example, iteration over ChangeLog entries can be implemented as
    02461  *  follows.
    02462  *
    02463  *    # iterate over ChangeLog entries.
    02464  *    open("ChangeLog") {|f|
    02465  *      f.slice_before(/\A\S/).each {|e| pp e}
    02466  *    }
    02467  *
    02468  *    # same as above.  block is used instead of pattern argument.
    02469  *    open("ChangeLog") {|f|
    02470  *      f.slice_before {|line| /\A\S/ === line }.each {|e| pp e}
    02471  *    }
    02472  *
    02473  * "svn proplist -R" produces multiline output for each file.
    02474  * They can be chunked as follows:
    02475  *
    02476  *    IO.popen([{"LC_ALL"=>"C"}, "svn", "proplist", "-R"]) {|f|
    02477  *      f.lines.slice_before(/\AProp/).each {|lines| p lines }
    02478  *    }
    02479  *    #=> ["Properties on '.':\n", "  svn:ignore\n", "  svk:merge\n"]
    02480  *    #   ["Properties on 'goruby.c':\n", "  svn:eol-style\n"]
    02481  *    #   ["Properties on 'complex.c':\n", "  svn:mime-type\n", "  svn:eol-style\n"]
    02482  *    #   ["Properties on 'regparse.c':\n", "  svn:eol-style\n"]
    02483  *    #   ...
    02484  *
    02485  *  If the block needs to maintain state over multiple elements,
    02486  *  local variables can be used.
    02487  *  For example, three or more consecutive increasing numbers can be squashed
    02488  *  as follows:
    02489  *
    02490  *    a = [0,2,3,4,6,7,9]
    02491  *    prev = a[0]
    02492  *    p a.slice_before {|e|
    02493  *      prev, prev2 = e, prev
    02494  *      prev2 + 1 != e
    02495  *    }.map {|es|
    02496  *      es.length <= 2 ? es.join(",") : "#{es.first}-#{es.last}"
    02497  *    }.join(",")
    02498  *    #=> "0,2-4,6,7,9"
    02499  *
    02500  *  However local variables are not appropriate to maintain state
    02501  *  if the result enumerator is used twice or more.
    02502  *  In such case, the last state of the 1st +each+ is used in 2nd +each+.
    02503  *  _initial_state_ argument can be used to avoid this problem.
    02504  *  If non-nil value is given as _initial_state_,
    02505  *  it is duplicated for each "each" method invocation of the enumerator.
    02506  *  The duplicated object is passed to 2nd argument of the block for
    02507  *  +slice_before+ method.
    02508  *
    02509  *    # word wrapping.
    02510  *    # this assumes all characters have same width.
    02511  *    def wordwrap(words, maxwidth)
    02512  *      # if cols is a local variable, 2nd "each" may start with non-zero cols.
    02513  *      words.slice_before(cols: 0) {|w, h|
    02514  *        h[:cols] += 1 if h[:cols] != 0
    02515  *        h[:cols] += w.length
    02516  *        if maxwidth < h[:cols]
    02517  *          h[:cols] = w.length
    02518  *          true
    02519  *        else
    02520  *          false
    02521  *        end
    02522  *      }
    02523  *    end
    02524  *    text = (1..20).to_a.join(" ")
    02525  *    enum = wordwrap(text.split(/\s+/), 10)
    02526  *    puts "-"*10
    02527  *    enum.each {|ws| puts ws.join(" ") }
    02528  *    puts "-"*10
    02529  *    #=> ----------
    02530  *    #   1 2 3 4 5
    02531  *    #   6 7 8 9 10
    02532  *    #   11 12 13
    02533  *    #   14 15 16
    02534  *    #   17 18 19
    02535  *    #   20
    02536  *    #   ----------
    02537  *
    02538  * mbox contains series of mails which start with Unix From line.
    02539  * So each mail can be extracted by slice before Unix From line.
    02540  *
    02541  *    # parse mbox
    02542  *    open("mbox") {|f|
    02543  *      f.slice_before {|line|
    02544  *        line.start_with? "From "
    02545  *      }.each {|mail|
    02546  *        unix_from = mail.shift
    02547  *        i = mail.index("\n")
    02548  *        header = mail[0...i]
    02549  *        body = mail[(i+1)..-1]
    02550  *        body.pop if body.last == "\n"
    02551  *        fields = header.slice_before {|line| !" \t".include?(line[0]) }.to_a
    02552  *        p unix_from
    02553  *        pp fields
    02554  *        pp body
    02555  *      }
    02556  *    }
    02557  *
    02558  *    # split mails in mbox (slice before Unix From line after an empty line)
    02559  *    open("mbox") {|f|
    02560  *      f.slice_before(emp: true) {|line,h|
    02561  *        prevemp = h[:emp]
    02562  *        h[:emp] = line == "\n"
    02563  *        prevemp && line.start_with?("From ")
    02564  *      }.each {|mail|
    02565  *        mail.pop if mail.last == "\n"
    02566  *        pp mail
    02567  *      }
    02568  *    }
    02569  *
    02570  */
    02571 static VALUE
    02572 enum_slice_before(int argc, VALUE *argv, VALUE enumerable)
    02573 {
    02574     VALUE enumerator;
    02575
    02576     if (rb_block_given_p()) {
    02577         VALUE initial_state;
    02578         rb_scan_args(argc, argv, "01", &initial_state);
    02579         enumerator = rb_obj_alloc(rb_cEnumerator);
    02580         rb_ivar_set(enumerator, rb_intern("slicebefore_sep_pred"), rb_block_proc());
    02581         rb_ivar_set(enumerator, rb_intern("slicebefore_initial_state"), initial_state);
    02582     }
    02583     else {
    02584         VALUE sep_pat;
    02585         rb_scan_args(argc, argv, "1", &sep_pat);
    02586         enumerator = rb_obj_alloc(rb_cEnumerator);
    02587         rb_ivar_set(enumerator, rb_intern("slicebefore_sep_pat"), sep_pat);
    02588     }
    02589     rb_ivar_set(enumerator, rb_intern("slicebefore_enumerable"), enumerable);
    02590     rb_block_call(enumerator, rb_intern("initialize"), 0, 0, slicebefore_i, enumerator);
    02591     return enumerator;
    02592 }
    02593
    02594 /*
    02595  *  The <code>Enumerable</code> mixin provides collection classes with
    02596  *  several traversal and searching methods, and with the ability to
    02597  *  sort. The class must provide a method <code>each</code>, which
    02598  *  yields successive members of the collection. If
    02599  *  <code>Enumerable#max</code>, <code>#min</code>, or
    02600  *  <code>#sort</code> is used, the objects in the collection must also
    02601  *  implement a meaningful <code><=></code> operator, as these methods
    02602  *  rely on an ordering between members of the collection.
    02603  */
    02604
    02605 void
    02606 Init_Enumerable(void)
    02607 {
    02608 #undef rb_intern
    02609 #define rb_intern(str) rb_intern_const(str)
    02610
    02611     rb_mEnumerable = rb_define_module("Enumerable");
    02612
    02613     rb_define_method(rb_mEnumerable, "to_a", enum_to_a, -1);
    02614     rb_define_method(rb_mEnumerable, "entries", enum_to_a, -1);
    02615
    02616     rb_define_method(rb_mEnumerable, "sort", enum_sort, 0);
    02617     rb_define_method(rb_mEnumerable, "sort_by", enum_sort_by, 0);
    02618     rb_define_method(rb_mEnumerable, "grep", enum_grep, 1);
    02619     rb_define_method(rb_mEnumerable, "count", enum_count, -1);
    02620     rb_define_method(rb_mEnumerable, "find", enum_find, -1);
    02621     rb_define_method(rb_mEnumerable, "detect", enum_find, -1);
    02622     rb_define_method(rb_mEnumerable, "find_index", enum_find_index, -1);
    02623     rb_define_method(rb_mEnumerable, "find_all", enum_find_all, 0);
    02624     rb_define_method(rb_mEnumerable, "select", enum_find_all, 0);
    02625     rb_define_method(rb_mEnumerable, "reject", enum_reject, 0);
    02626     rb_define_method(rb_mEnumerable, "collect", enum_collect, 0);
    02627     rb_define_method(rb_mEnumerable, "map", enum_collect, 0);
    02628     rb_define_method(rb_mEnumerable, "flat_map", enum_flat_map, 0);
    02629     rb_define_method(rb_mEnumerable, "collect_concat", enum_flat_map, 0);
    02630     rb_define_method(rb_mEnumerable, "inject", enum_inject, -1);
    02631     rb_define_method(rb_mEnumerable, "reduce", enum_inject, -1);
    02632     rb_define_method(rb_mEnumerable, "partition", enum_partition, 0);
    02633     rb_define_method(rb_mEnumerable, "group_by", enum_group_by, 0);
    02634     rb_define_method(rb_mEnumerable, "first", enum_first, -1);
    02635     rb_define_method(rb_mEnumerable, "all?", enum_all, 0);
    02636     rb_define_method(rb_mEnumerable, "any?", enum_any, 0);
    02637     rb_define_method(rb_mEnumerable, "one?", enum_one, 0);
    02638     rb_define_method(rb_mEnumerable, "none?", enum_none, 0);
    02639     rb_define_method(rb_mEnumerable, "min", enum_min, 0);
    02640     rb_define_method(rb_mEnumerable, "max", enum_max, 0);
    02641     rb_define_method(rb_mEnumerable, "minmax", enum_minmax, 0);
    02642     rb_define_method(rb_mEnumerable, "min_by", enum_min_by, 0);
    02643     rb_define_method(rb_mEnumerable, "max_by", enum_max_by, 0);
    02644     rb_define_method(rb_mEnumerable, "minmax_by", enum_minmax_by, 0);
    02645     rb_define_method(rb_mEnumerable, "member?", enum_member, 1);
    02646     rb_define_method(rb_mEnumerable, "include?", enum_member, 1);
    02647     rb_define_method(rb_mEnumerable, "each_with_index", enum_each_with_index, -1);
    02648     rb_define_method(rb_mEnumerable, "reverse_each", enum_reverse_each, -1);
    02649     rb_define_method(rb_mEnumerable, "each_entry", enum_each_entry, -1);
    02650     rb_define_method(rb_mEnumerable, "each_slice", enum_each_slice, 1);
    02651     rb_define_method(rb_mEnumerable, "each_cons", enum_each_cons, 1);
    02652     rb_define_method(rb_mEnumerable, "each_with_object", enum_each_with_object, 1);
    02653     rb_define_method(rb_mEnumerable, "zip", enum_zip, -1);
    02654     rb_define_method(rb_mEnumerable, "take", enum_take, 1);
    02655     rb_define_method(rb_mEnumerable, "take_while", enum_take_while, 0);
    02656     rb_define_method(rb_mEnumerable, "drop", enum_drop, 1);
    02657     rb_define_method(rb_mEnumerable, "drop_while", enum_drop_while, 0);
    02658     rb_define_method(rb_mEnumerable, "cycle", enum_cycle, -1);
    02659     rb_define_method(rb_mEnumerable, "chunk", enum_chunk, -1);
    02660     rb_define_method(rb_mEnumerable, "slice_before", enum_slice_before, -1);
    02661
    02662     id_eqq  = rb_intern("===");
    02663     id_each = rb_intern("each");
    02664     id_cmp  = rb_intern("<=>");
    02665     id_next = rb_intern("next");
    02666     id_size = rb_intern("size");
    02667 }
    02668
    02669