This is a Swift framework providing a single collection interface, ReducibleType
, suitable for representing the traversal of collections.
ReducibleType
, provides both enumeration and iteration.reduce
& iterate with Stream
.Stream
makes a reducible from SequenceType
; sequence()
supports for
…in
(and other clients of SequenceType
) with any ReducibleType
.Stream
& sequence
support any SequenceType
provider or client; ReducibleType
is similar to recursive reduce
.Stream
is pure; retrieving the current element does not advance/mutate the stream; memoizes, avoiding repeated effects in impure producers.Stream
evaluates lazily; reduce
can be halted early; supports unbounded collections.SequenceType
/GeneratorType
?Swift’s SequenceType
& GeneratorType
interfaces support sequential traversal. However, they have several key drawbacks:
Fragility: requires mutable state; no access to the current element without mutating.
Difficulty of adoption: SequenceType
can be hard to implement; requirement to mutate makes debugging harder.
Difficulty of use: advancing is subtle; correct backtracking requires (essentially) Stream
; no access to the current element without mutating.
Complexity: ad hoc constraints which the compiler cannot enforce; constraints may differ between implementations; copies of generators are legal but should not be advanced separately; untenable promotion to even more complex CollectionType
instead; per the comments:
Any code that uses multiple generators (or
for
…in
loops) over a single sequence should have static knowledge that the specific sequence is multi-pass, either because its concrete type is known or because it is constrained toCollectionType
. Also, the generators must be obtained by distinct calls to the sequence'sgenerate()
method, rather than by copying.
Inefficiency: Iteration (sequential access by client code calling into API) is generally less efficient than enumeration (sequential access by API calling into client code).
In contrast, Traversal’s ReducibleType
interface does not depend on mutable state, enabling pure implementations, and provides a consistent, reliable basis for both enumeration and iteration at the caller’s discretion, with only a single method to implement.
Check out this repository on your Mac:
git clone https://github.com/robrix/Traversal.git
Check out its dependencies:
git submodule update --init --recursive
Open Traversal.xcworkspace
.
Build the Traversal
target.
Traversal.xcodeproj
into your project or workspace, and do the same with its dependencies (i.e. the other .xcodeproj
files included in Traversal.xcworkspace
). NB: Traversal.xcworkspace
is for standalone development of Traversal, while Traversal.xcodeproj
is for targets using Traversal as a dependency.Traversal.framework
and each of the dependency frameworks.