summaryrefslogtreecommitdiff
path: root/enum.c
diff options
context:
space:
mode:
authorTanaka Akira <[email protected]>2025-04-22 01:49:41 +0900
committerTanaka Akira <[email protected]>2025-04-22 01:49:41 +0900
commitfa17cb75a1a79b6c3fb1e70acc5a4a589efa23e8 (patch)
tree0fe77e11df76b6eb51063f5e044f76653c4e4c8d /enum.c
parentff689b9a7ac01d512619e28cd832271f85295e6a (diff)
[doc] update Enumerable document.
- Enhance document about #size method for Enumerable and Enumerator - add an Enumerator example for Enumerable#drop_while
Diffstat (limited to 'enum.c')
-rw-r--r--enum.c83
1 files changed, 63 insertions, 20 deletions
diff --git a/enum.c b/enum.c
index 537ecf5532..182e4f6e83 100644
--- a/enum.c
+++ b/enum.c
@@ -3704,6 +3704,17 @@ drop_while_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
*
* With no block given, returns an Enumerator.
*
+ * e = (1..4).drop_while
+ * p e #=> #<Enumerator: 1..4:drop_while>
+ * i = e.next; p i; e.feed(i < 3) #=> 1
+ * i = e.next; p i; e.feed(i < 3) #=> 2
+ * i = e.next; p i; e.feed(i < 3) #=> 3
+ * begin
+ * e.next
+ * rescue StopIteration
+ * p $!.result #=> [3, 4]
+ * end
+ *
*/
static VALUE
@@ -5115,11 +5126,34 @@ enum_compact(VALUE obj)
*
* === #size
*
- * \Enumerator has #size method.
- * It uses the size function argument for +Enumerator.new+.
- * It should returns the number of iterations (number of #each method yields).
- * The result is integer or +Float::INFINITY+.
- * However it may also return nil when it is difficult to determine the result.
+ * \Enumerator has a #size method.
+ * It uses the size function argument passed to +Enumerator.new+.
+ *
+ * e = Enumerator.new(-> { 3 }) {|y| p y; y.yield :a; y.yield :b; y.yield :c; :z }
+ * p e.size #=> 3
+ * p e.next #=> :a
+ * p e.next #=> :b
+ * p e.next #=> :c
+ * begin
+ * e.next
+ * rescue StopIteration
+ * p $!.result #=> :z
+ * end
+ *
+ * The result of the size function should represent the number of iterations
+ * (i.e., the number of times Enumerator::Yielder#yield is called).
+ * In the above example, the block calls #yield three times, and
+ * the size function, +-> { 3 }+, returns 3 accordingly.
+ * The result of the size function can be an integer, +Float::INFINITY+,
+ * or +nil+.
+ * An integer means the exact number of times #yield will be called,
+ * as shown above.
+ * +Float::INFINITY+ indicates an infinite number of #yield calls.
+ * +nil+ means the number of #yield calls is difficult or impossible to
+ * determine.
+ *
+ * Many iteration methods return an \Enumerator object with an
+ * appropriate size function if no block is given.
*
* Examples:
*
@@ -5127,30 +5161,39 @@ enum_compact(VALUE obj)
* {a: "x", b: "y", c: "z"}.each.size #=> 3
* (0..20).to_a.permutation.size #=> 51090942171709440000
* loop.size #=> Float::INFINITY
- * (1..100).drop_while.size #=> nil # the size depends on the block values
- * File.open("/etc/resolv.conf").each.size #=> nil # not computable without actually read the file.
+ * (1..100).drop_while.size #=> nil # size depends on the block's behavior
+ * STDIN.each.size #=> nil # cannot be computed without consuming input
+ * File.open("/etc/resolv.conf").each.size #=> nil # cannot be computed without reading the file
*
- * The behavior of #size of Range-based enumerator depends on the #begin element.
-
- * * If the #begin element is an integer, #size methd returns integer or +Float::INFINITY+.
- * * If the #begin element is an object with #succ method except integer, #size methd returns nil.
- * (It is too slow to compute the size by calling #succ repeatedly)
- * * If the #begin element is an object without #succ method, #size method raises TypeError.
+ * The behavior of #size for Range-based enumerators depends on the #begin element:
+ *
+ * - If the #begin element is an Integer, the #size method returns an Integer or +Float::INFINITY+.
+ * - If the #begin element is an object with a #succ method (other than Integer), #size returns +nil+.
+ * (Computing the size would require repeatedly calling #succ, which may be too slow.)
+ * - If the #begin element does not have a #succ method, #size raises a TypeError.
*
* Examples:
*
* (10..42).each.size #=> 33
- * (10..42.9).each.size #=> 33 (#end element can be numeric other than integer)
+ * (10..42.9).each.size #=> 33 (the #end element may be a non-integer numeric)
* (10..).each.size #=> Float::INFINITY
* ("a".."z").each.size #=> nil
* ("a"..).each.size #=> nil
- * (1.0..9.0).each.size # raises TypeError (There is no Float#succ)
- * (..10).each.size # raises TypeError (beginless range has nil as #begin element)
+ * (1.0..9.0).each.size # raises TypeError (Float does not have #succ)
+ * (..10).each.size # raises TypeError (beginless range has nil as its #begin)
+ *
+ * The \Enumerable module itself does not define a #size method.
+ * A class that includes \Enumerable may define its own #size method.
+ * It is recommended that such a #size method be consistent with
+ * Enumerator#size.
+ *
+ * Array and Hash implement #size and return values consistent with
+ * Enumerator#size.
+ * IO and Dir do not define #size, which is also consistent because the
+ * corresponding enumerator's size function returns +nil+.
*
- * \Enumerable classes may have #size method.
- * It returns the result same as Enumerator#size in most cases: Array, Hash.
- * Some classes have no #size method: IO, Dir.
- * (Note that File#size is not related to File#each. It returns nubmer of bytes instead of number of lines.)
+ * However, it is not strictly required for a class's #size method to match Enumerator#size.
+ * For example, File#size returns the number of bytes in the file, not the number of lines.
*
*/