Structs

The following structs are available globally.

  • Monadic implementation of continuation passing style (CPS). An instance of Continuation<R, A> represents a computation resulting in an A value. By passing a continuation of type A -> R, a Continuation<R, A> will use the A result and the continuation to produce an R.

    See more

    Declaration

    Swift

    public struct Continuation<R, A>
  • A lazy, asynchronous, concurrent, and reusable stream of operations on elements of data.

    let sum = (1..<50000).stream()
        .filter { $0 % 2 == 0 }
        .reduce(0, reducer: +)
        .wait()
    

    This example makes a stream from the collection created by (1..<50000). Then it filters out from that stream all elements that aren’t even. Then it reduces the stream; it starts at 0, then uses + to combine all elements. Streams work asynchronously, so wait() is called to wait on the result.

    There are three stages to using streams.

    • Create the stream

      Most often, a stream will be created using CollectionType.stream(), or Stream.of(T...). But it is possible to create custom streams.

      A stream uses the Continuation monad to pass elements to handlers. A continuation is specialized to the type Continuation<Future<()>, T>. It returns a Future<()> because the handlers are asynchronous. The goal is to create a continuation that will call the handler once for each element. This is encouraged to be concurrent. A stream shouldn’t complete its future until all the futures returned by the handler are completed.

      The future’s type is Future<()> because it is isomorphic to (). That is to say there is no actual return value. The only thing that matters is the time of completion.

    • Manipulate the stream

      There are several intermediary operations to manipulate the stream. The simplest is Stream<T>.map(T -> U). This returns a stream that maps elements of the original stream to elements of a different type.

      Streams are immutable, lazy, and reusable, so intermediary operations aren’t changing the stream or its elements. Instead, they construct a new stream that will get its elements from the old stream, and modify them accordingly before passing the element to a handler.

    • Run the stream

      Terminal operations on a stream will start running the stream. Most often, the stream will run asynchronously and concurrently, but this depends on the how the stream was created. Running a stream means to start accepting elements of the stream with a handler. The simplest example of this is Stream.forEach, which calls a handler for each element.

      Most streams are concurrent. This leads to dramatic performance improvements in many scenarios. There are, however, situations where the overhead of concurrency outweights the performance gains. For example, there are two different methods of reducing a stream. One is psuedo-serial, in that the reduction is performed serially, while the elements are computed concurrently. The other is fully concurrent, where both the computation of elements and the reduction are concurrent. For very fast reduction functions, the psuedo-serial method is usually faster, since there’s no concurrency overhead. For slower reduction functions, the concurrent method is usually faster, since more reductions can be occurring at a time.

    Streams and collections differ in several ways. Besides being concurrent and asynchronous, streams are lazy and unordered. Streams do not store elements, and instead rely on abstract data sources. They can’t have their count calculated. Most importantly, Stream is not a data structure. It is a pipeline for manipulating elements, no matter how many there are. This is the inspiration for using the Continuation monad.

    See more

    Declaration

    Swift

    public struct Stream<T>
  • A Channel is a frontend for receiving values written to a ChannelWriter. A Channel provides an interface for adding handlers for these values, as well as ways to create new Channels that change values before passing them to handlers. Each handler is only ever called once; with the next value the channel receives after adding it.

    See more

    Declaration

    Swift

    public struct Channel<T>
  • A Future represents a value to be determined later. Future provides an interface for manipulating that value.

    future
        .map { $0 + 1 }
        .flatMap { $0.futureComp() }
        .onComplete { print($0) }
    
    See more

    Declaration

    Swift

    public struct Future<T>