| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- //
- // RACSequence.h
- // ReactiveCocoa
- //
- // Created by Justin Spahr-Summers on 2012-10-29.
- // Copyright (c) 2012 GitHub. All rights reserved.
- //
- #import <Foundation/Foundation.h>
- #import "RACStream.h"
- @class RACScheduler;
- @class RACSignal;
- /// Represents an immutable sequence of values. Unless otherwise specified, the
- /// sequences' values are evaluated lazily on demand. Like Cocoa collections,
- /// sequences cannot contain nil.
- ///
- /// Most inherited RACStream methods that accept a block will execute the block
- /// _at most_ once for each value that is evaluated in the returned sequence.
- /// Side effects are subject to the behavior described in
- /// +sequenceWithHeadBlock:tailBlock:.
- ///
- /// Implemented as a class cluster. A minimal implementation for a subclass
- /// consists simply of -head and -tail.
- @interface RACSequence : RACStream <NSCoding, NSCopying, NSFastEnumeration>
- /// The first object in the sequence, or nil if the sequence is empty.
- ///
- /// Subclasses must provide an implementation of this method.
- @property (nonatomic, strong, readonly) id head;
- /// All but the first object in the sequence, or nil if there are no other
- /// objects.
- ///
- /// Subclasses must provide an implementation of this method.
- @property (nonatomic, strong, readonly) RACSequence *tail;
- /// Evaluates the full sequence to produce an equivalently-sized array.
- @property (nonatomic, copy, readonly) NSArray *array;
- /// Returns an enumerator of all objects in the sequence.
- @property (nonatomic, copy, readonly) NSEnumerator *objectEnumerator;
- /// Converts a sequence into an eager sequence.
- ///
- /// An eager sequence fully evaluates all of its values immediately. Sequences
- /// derived from an eager sequence will also be eager.
- ///
- /// Returns a new eager sequence, or the receiver if the sequence is already
- /// eager.
- @property (nonatomic, copy, readonly) RACSequence *eagerSequence;
- /// Converts a sequence into a lazy sequence.
- ///
- /// A lazy sequence evaluates its values on demand, as they are accessed.
- /// Sequences derived from a lazy sequence will also be lazy.
- ///
- /// Returns a new lazy sequence, or the receiver if the sequence is already lazy.
- @property (nonatomic, copy, readonly) RACSequence *lazySequence;
- /// Invokes -signalWithScheduler: with a new RACScheduler.
- - (RACSignal *)signal;
- /// Evaluates the full sequence on the given scheduler.
- ///
- /// Each item is evaluated in its own scheduled block, such that control of the
- /// scheduler is yielded between each value.
- ///
- /// Returns a signal which sends the receiver's values on the given scheduler as
- /// they're evaluated.
- - (RACSignal *)signalWithScheduler:(RACScheduler *)scheduler;
- /// Applies a left fold to the sequence.
- ///
- /// This is the same as iterating the sequence along with a provided start value.
- /// This uses a constant amount of memory. A left fold is left-associative so in
- /// the sequence [1,2,3] the block would applied in the following order:
- /// reduce(reduce(reduce(start, 1), 2), 3)
- ///
- /// start - The starting value for the fold. Used as `accumulator` for the
- /// first fold.
- /// reduce - The block used to combine the accumulated value and the next value.
- /// Cannot be nil.
- ///
- /// Returns a reduced value.
- - (id)foldLeftWithStart:(id)start reduce:(id (^)(id accumulator, id value))reduce;
- /// Applies a right fold to the sequence.
- ///
- /// A right fold is equivalent to recursion on the list. The block is evaluated
- /// from the right to the left in list. It is right associative so it's applied
- /// to the rightmost elements first. For example, in the sequence [1,2,3] the
- /// block is applied in the order:
- /// reduce(1, reduce(2, reduce(3, start)))
- ///
- /// start - The starting value for the fold.
- /// reduce - The block used to combine the accumulated value and the next head.
- /// The block is given the accumulated value and the value of the rest
- /// of the computation (result of the recursion). This is computed when
- /// you retrieve its value using `rest.head`. This allows you to
- /// prevent unnecessary computation by not accessing `rest.head` if you
- /// don't need to.
- ///
- /// Returns a reduced value.
- - (id)foldRightWithStart:(id)start reduce:(id (^)(id first, RACSequence *rest))reduce;
- /// Check if any value in sequence passes the block.
- ///
- /// block - The block predicate used to check each item. Cannot be nil.
- ///
- /// Returns a boolean indiciating if any value in the sequence passed.
- - (BOOL)any:(BOOL (^)(id value))block;
- /// Check if all values in the sequence pass the block.
- ///
- /// block - The block predicate used to check each item. Cannot be nil.
- ///
- /// Returns a boolean indicating if all values in the sequence passed.
- - (BOOL)all:(BOOL (^)(id value))block;
- /// Returns the first object that passes the block.
- ///
- /// block - The block predicate used to check each item. Cannot be nil.
- ///
- /// Returns an object that passes the block or nil if no objects passed.
- - (id)objectPassingTest:(BOOL (^)(id value))block;
- /// Creates a sequence that dynamically generates its values.
- ///
- /// headBlock - Invoked the first time -head is accessed.
- /// tailBlock - Invoked the first time -tail is accessed.
- ///
- /// The results from each block are memoized, so each block will be invoked at
- /// most once, no matter how many times the head and tail properties of the
- /// sequence are accessed.
- ///
- /// Any side effects in `headBlock` or `tailBlock` should be thread-safe, since
- /// the sequence may be evaluated at any time from any thread. Not only that, but
- /// -tail may be accessed before -head, or both may be accessed simultaneously.
- /// As noted above, side effects will only be triggered the _first_ time -head or
- /// -tail is invoked.
- ///
- /// Returns a sequence that lazily invokes the given blocks to provide head and
- /// tail. `headBlock` must not be nil.
- + (RACSequence *)sequenceWithHeadBlock:(id (^)(void))headBlock tailBlock:(RACSequence *(^)(void))tailBlock;
- @end
- @interface RACSequence (Unavailable)
- - (id)foldLeftWithStart:(id)start combine:(id (^)(id accumulator, id value))combine __attribute__((unavailable("Renamed to -foldLeftWithStart:reduce:")));
- - (id)foldRightWithStart:(id)start combine:(id (^)(id first, RACSequence *rest))combine __attribute__((unavailable("Renamed to -foldRightWithStart:reduce:")));
- @end
|