diff --git a/core/enumerator.rbs b/core/enumerator.rbs index 9187574b4..fe33b820b 100644 --- a/core/enumerator.rbs +++ b/core/enumerator.rbs @@ -124,6 +124,43 @@ class Enumerator[unchecked out Elem, out Return] < Object include Enumerable[Elem] + # + # Creates an infinite enumerator from any block, just called over and over. The + # result of the previous iteration is passed to the next one. If `initial` is + # provided, it is passed to the first iteration, and becomes the first element + # of the enumerator; if it is not provided, the first iteration receives `nil`, + # and its result becomes the first element of the iterator. + # + # Raising StopIteration from the block stops an iteration. + # + # Enumerator.produce(1, &:succ) # => enumerator of 1, 2, 3, 4, .... + # + # Enumerator.produce { rand(10) } # => infinite random number sequence + # + # ancestors = Enumerator.produce(node) { |prev| node = prev.parent or raise StopIteration } + # enclosing_section = ancestors.find { |n| n.type == :section } + # + # Using ::produce together with Enumerable methods like Enumerable#detect, + # Enumerable#slice_after, Enumerable#take_while can provide Enumerator-based + # alternatives for `while` and `until` cycles: + # + # # Find next Tuesday + # require "date" + # Enumerator.produce(Date.today, &:succ).detect(&:tuesday?) + # + # # Simple lexer: + # require "strscan" + # scanner = StringScanner.new("7+38/6") + # PATTERN = %r{\d+|[-/+*]} + # Enumerator.produce { scanner.scan(PATTERN) }.slice_after { scanner.eos? }.first + # # => ["7", "+", "38", "/", "6"] + # + def self.produce: [T] () { (T? prev) -> T } -> Enumerator[T, bot] + | [T] (T initial) { (T prev) -> T } -> Enumerator[T, bot] + #