lib/enumerator.fy in fancy-0.3.3 vs lib/enumerator.fy in fancy-0.4.0
- old
+ new
@@ -1,16 +1,46 @@
class FancyEnumerator {
- def initialize: @object {
+ def initialize: @collection {
+ """
+ @collection Collection to iterate over.
+
+ Initializes a new FancyEnumerator with a given @collection,
+ using #each: for iteration.
+ """
+
@iterator = 'each:
rewind
}
- def initialize: @object with: @iterator {
+ def initialize: @collection with: @iterator {
+ """
+ @collection Collection to iterate over.
+ @iterator Selector to use to iterate over @collection.
+
+ Initializes a new FancyEnumerator with a given @collection
+ and @iterator selector to be used for iteration.
+ """
+
rewind
}
def next {
+ """
+ @return Next element in the collection this enumerator is attached to.
+
+ Returns the next element in the collection this enumerator is attached to.
+ It will move the internal position forward (compared to e.g. #peek, which doesn't).
+
+ Example:
+ a = [1,2,3]
+ e = a to_enum
+ e next # => 1
+ e next # => 2
+ e next # => 3
+ e next # => raises Fancy StopIteration
+ """
+
if: @peeked then: {
@peeked = false
@peek
} else: {
result = @fiber resume
@@ -20,26 +50,37 @@
(Fancy StopIteration new: result) raise!
}
}
}
+ def ended? {
+ """
+ @return @true if the enumerator has ended (no more values left), @false otherwise.
+
+ Indicates if an enumerator has ended (no more values left).
+ """
+
+ @fiber alive? not
+ }
+
def peek {
"""
Returns the next object in the FancyEnumerator, but doesn't move the
internal position forward.
When the position reaches the end, a Fancy StopIteration exception is
raised.
- a = [1,2,3]
- e = a to_enum
- e next p #=> 1
- e peek p #=> 2
- e peek p #=> 2
- e peek p #=> 2
- e next p #=> 2
- e next p #=> 3
- e next p #=> raises Fancy StopIteration
+ Example:
+ a = [1,2,3]
+ e = a to_enum
+ e next p #=> 1
+ e peek p #=> 2
+ e peek p #=> 2
+ e peek p #=> 2
+ e next p #=> 2
+ e next p #=> 3
+ e next p #=> raises Fancy StopIteration
"""
unless: @peeked do: {
@peeked = true
@peek = @fiber resume
@@ -52,26 +93,92 @@
return @peek
}
def rewind {
+ """
+ Resets the enumerator to start from the collection's beginning.
+ """
+
@peeked = false
@peek = nil
@fiber = Fiber new: {
param = |element| { yield: element }
- @object send_message: @iterator with_params: [param]
+ @collection receive_message: @iterator with_params: [param]
}
}
def with: object each: block {
+ """
+ @object Object to pass along to @block with each element in the collection.
+ @block A @Block@ to be called with each element in the collection and @object.
+
+ Similar to #each: but also passing in a given @object to each invocation of @block.
+ """
+
+ each: |element| {
+ block call: [element, object]
+ }
+
+ return object
+ }
+
+ def each: block {
+ """
+ @block @Block@ to be called with each element in the collection (iteration).
+
+ Calls a given @Block@ with each element in the collection this enumerator is attached to.
+ Used for iterating over the collection using this enumerator.
+ """
+
loop: {
try {
- block call: [next, object]
+ block call: [next]
} catch (Fancy StopIteration) => ex {
- return object
+ return self
}
}
+ }
- return object
+ def chunk: block {
+ Generator new: |inner_block| {
+ enums = []
+ last = nil
+ previous = nil
+ stack = []
+
+ each: |element| {
+ result = (block call: [element]) not not
+ if: (previous == result) then: {
+ stack << element
+ } else: {
+ previous if_nil: {
+ # wait one gap to call
+ } else: {
+ inner_block call: [[previous, stack]]
+ }
+ previous = result
+ stack = [element]
+ last = [result, stack]
+ enums << last
+ }
+ }
+
+ self
+ } . to_enum
+ }
+
+ class Generator {
+ def initialize: @block {}
+
+ def each: block {
+ @block call: [block]
+ }
+ }
+
+ def to_a {
+ output = []
+ each: |element| { output << element }
+ output
}
}