RACSequence.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. //
  2. // RACSequence.h
  3. // ReactiveObjC
  4. //
  5. // Created by Justin Spahr-Summers on 2012-10-29.
  6. // Copyright (c) 2012 GitHub. All rights reserved.
  7. //
  8. #import <Foundation/Foundation.h>
  9. #import "RACStream.h"
  10. @class RACTuple;
  11. @class RACScheduler;
  12. @class RACSignal<__covariant ValueType>;
  13. NS_ASSUME_NONNULL_BEGIN
  14. /// Represents an immutable sequence of values. Unless otherwise specified, the
  15. /// sequences' values are evaluated lazily on demand. Like Cocoa collections,
  16. /// sequences cannot contain nil.
  17. ///
  18. /// Most inherited RACStream methods that accept a block will execute the block
  19. /// _at most_ once for each value that is evaluated in the returned sequence.
  20. /// Side effects are subject to the behavior described in
  21. /// +sequenceWithHeadBlock:tailBlock:.
  22. ///
  23. /// Implemented as a class cluster. A minimal implementation for a subclass
  24. /// consists simply of -head and -tail.
  25. @interface RACSequence<__covariant ValueType> : RACStream <NSCoding, NSCopying, NSFastEnumeration>
  26. /// The first object in the sequence, or nil if the sequence is empty.
  27. ///
  28. /// Subclasses must provide an implementation of this method.
  29. @property (nonatomic, strong, readonly, nullable) ValueType head;
  30. /// All but the first object in the sequence, or nil if there are no other
  31. /// objects.
  32. ///
  33. /// Subclasses must provide an implementation of this method.
  34. @property (nonatomic, strong, readonly, nullable) RACSequence<ValueType> *tail;
  35. /// Evaluates the full sequence to produce an equivalently-sized array.
  36. @property (nonatomic, copy, readonly) NSArray<ValueType> *array;
  37. /// Returns an enumerator of all objects in the sequence.
  38. @property (nonatomic, copy, readonly) NSEnumerator<ValueType> *objectEnumerator;
  39. /// Converts a sequence into an eager sequence.
  40. ///
  41. /// An eager sequence fully evaluates all of its values immediately. Sequences
  42. /// derived from an eager sequence will also be eager.
  43. ///
  44. /// Returns a new eager sequence, or the receiver if the sequence is already
  45. /// eager.
  46. @property (nonatomic, copy, readonly) RACSequence<ValueType> *eagerSequence;
  47. /// Converts a sequence into a lazy sequence.
  48. ///
  49. /// A lazy sequence evaluates its values on demand, as they are accessed.
  50. /// Sequences derived from a lazy sequence will also be lazy.
  51. ///
  52. /// Returns a new lazy sequence, or the receiver if the sequence is already lazy.
  53. @property (nonatomic, copy, readonly) RACSequence<ValueType> *lazySequence;
  54. /// Invokes -signalWithScheduler: with a new RACScheduler.
  55. - (RACSignal<ValueType> *)signal;
  56. /// Evaluates the full sequence on the given scheduler.
  57. ///
  58. /// Each item is evaluated in its own scheduled block, such that control of the
  59. /// scheduler is yielded between each value.
  60. ///
  61. /// Returns a signal which sends the receiver's values on the given scheduler as
  62. /// they're evaluated.
  63. - (RACSignal<ValueType> *)signalWithScheduler:(RACScheduler *)scheduler;
  64. /// Applies a left fold to the sequence.
  65. ///
  66. /// This is the same as iterating the sequence along with a provided start value.
  67. /// This uses a constant amount of memory. A left fold is left-associative so in
  68. /// the sequence [1,2,3] the block would applied in the following order:
  69. /// reduce(reduce(reduce(start, 1), 2), 3)
  70. ///
  71. /// start - The starting value for the fold. Used as `accumulator` for the
  72. /// first fold.
  73. /// reduce - The block used to combine the accumulated value and the next value.
  74. /// Cannot be nil.
  75. ///
  76. /// Returns a reduced value.
  77. - (id)foldLeftWithStart:(nullable id)start reduce:(id _Nullable (^)(id _Nullable accumulator, ValueType _Nullable value))reduce;
  78. /// Applies a right fold to the sequence.
  79. ///
  80. /// A right fold is equivalent to recursion on the list. The block is evaluated
  81. /// from the right to the left in list. It is right associative so it's applied
  82. /// to the rightmost elements first. For example, in the sequence [1,2,3] the
  83. /// block is applied in the order:
  84. /// reduce(1, reduce(2, reduce(3, start)))
  85. ///
  86. /// start - The starting value for the fold.
  87. /// reduce - The block used to combine the accumulated value and the next head.
  88. /// The block is given the accumulated value and the value of the rest
  89. /// of the computation (result of the recursion). This is computed when
  90. /// you retrieve its value using `rest.head`. This allows you to
  91. /// prevent unnecessary computation by not accessing `rest.head` if you
  92. /// don't need to.
  93. ///
  94. /// Returns a reduced value.
  95. - (id)foldRightWithStart:(nullable id)start reduce:(id _Nullable (^)(id _Nullable first, RACSequence *rest))reduce;
  96. /// Check if any value in sequence passes the block.
  97. ///
  98. /// block - The block predicate used to check each item. Cannot be nil.
  99. ///
  100. /// Returns a boolean indiciating if any value in the sequence passed.
  101. - (BOOL)any:(BOOL (^)(ValueType _Nullable value))block;
  102. /// Check if all values in the sequence pass the block.
  103. ///
  104. /// block - The block predicate used to check each item. Cannot be nil.
  105. ///
  106. /// Returns a boolean indicating if all values in the sequence passed.
  107. - (BOOL)all:(BOOL (^)(ValueType _Nullable value))block;
  108. /// Returns the first object that passes the block.
  109. ///
  110. /// block - The block predicate used to check each item. Cannot be nil.
  111. ///
  112. /// Returns an object that passes the block or nil if no objects passed.
  113. - (nullable ValueType)objectPassingTest:(BOOL (^)(ValueType _Nullable value))block;
  114. /// Creates a sequence that dynamically generates its values.
  115. ///
  116. /// headBlock - Invoked the first time -head is accessed.
  117. /// tailBlock - Invoked the first time -tail is accessed.
  118. ///
  119. /// The results from each block are memoized, so each block will be invoked at
  120. /// most once, no matter how many times the head and tail properties of the
  121. /// sequence are accessed.
  122. ///
  123. /// Any side effects in `headBlock` or `tailBlock` should be thread-safe, since
  124. /// the sequence may be evaluated at any time from any thread. Not only that, but
  125. /// -tail may be accessed before -head, or both may be accessed simultaneously.
  126. /// As noted above, side effects will only be triggered the _first_ time -head or
  127. /// -tail is invoked.
  128. ///
  129. /// Returns a sequence that lazily invokes the given blocks to provide head and
  130. /// tail. `headBlock` must not be nil.
  131. + (RACSequence<ValueType> *)sequenceWithHeadBlock:(ValueType _Nullable (^)(void))headBlock tailBlock:(nullable RACSequence<ValueType> *(^)(void))tailBlock;
  132. @end
  133. @interface RACSequence<__covariant ValueType> (RACStream)
  134. /// Returns a sequence that immediately sends the given value and then completes.
  135. + (RACSequence<ValueType> *)return:(nullable ValueType)value;
  136. /// Returns a sequence that immediately completes.
  137. + (RACSequence<ValueType> *)empty;
  138. /// A block which accepts a value from a RACSequence and returns a new sequence.
  139. ///
  140. /// Setting `stop` to `YES` will cause the bind to terminate after the returned
  141. /// value. Returning `nil` will result in immediate termination.
  142. typedef RACSequence * _Nullable (^RACSequenceBindBlock)(ValueType _Nullable value, BOOL *stop);
  143. /// Lazily binds a block to the values in the receiver.
  144. ///
  145. /// This should only be used if you need to terminate the bind early, or close
  146. /// over some state. -flattenMap: is more appropriate for all other cases.
  147. ///
  148. /// block - A block returning a RACSequenceBindBlock. This block will be invoked
  149. /// each time the bound sequence is re-evaluated. This block must not be
  150. /// nil or return nil.
  151. ///
  152. /// Returns a new sequence which represents the combined result of all lazy
  153. /// applications of `block`.
  154. - (RACSequence *)bind:(RACSequenceBindBlock (^)(void))block;
  155. /// Subscribes to `sequence` when the source sequence completes.
  156. - (RACSequence *)concat:(RACSequence *)sequence;
  157. /// Zips the values in the receiver with those of the given sequence to create
  158. /// RACTuples.
  159. ///
  160. /// The first `next` of each sequence will be combined, then the second `next`,
  161. /// and so forth, until either sequence completes or errors.
  162. ///
  163. /// sequence - The sequence to zip with. This must not be `nil`.
  164. ///
  165. /// Returns a new sequence of RACTuples, representing the combined values of the
  166. /// two sequences. Any error from one of the original sequence will be forwarded
  167. /// on the returned sequence.
  168. - (RACSequence<RACTuple *> *)zipWith:(RACSequence *)sequence;
  169. @end
  170. /// Redeclarations of operations built on the RACStream primitives with more
  171. /// precise type information.
  172. @interface RACSequence<__covariant ValueType> (RACStreamOperations)
  173. /// Maps `block` across the values in the receiver and flattens the result.
  174. ///
  175. /// Note that operators applied _after_ -flattenMap: behave differently from
  176. /// operators _within_ -flattenMap:. See the Examples section below.
  177. ///
  178. /// This corresponds to the `SelectMany` method in Rx.
  179. ///
  180. /// block - A block which accepts the values in the receiver and returns a new
  181. /// instance of the receiver's class. Returning `nil` from this block is
  182. /// equivalent to returning an empty sequence.
  183. ///
  184. /// Returns a new sequence which represents the combined sequences resulting
  185. /// from mapping `block`.
  186. - (RACSequence *)flattenMap:(__kindof RACSequence * _Nullable (^)(ValueType _Nullable value))block;
  187. /// Flattens a sequence of sequences.
  188. ///
  189. /// This corresponds to the `Merge` method in Rx.
  190. ///
  191. /// Returns a sequence consisting of the combined sequences obtained from the
  192. /// receiver.
  193. - (RACSequence *)flatten;
  194. /// Maps `block` across the values in the receiver.
  195. ///
  196. /// This corresponds to the `Select` method in Rx.
  197. ///
  198. /// Returns a new sequence with the mapped values.
  199. - (RACSequence *)map:(id _Nullable (^)(ValueType _Nullable value))block;
  200. /// Replaces each value in the receiver with the given object.
  201. ///
  202. /// Returns a new sequence which includes the given object once for each value in
  203. /// the receiver.
  204. - (RACSequence *)mapReplace:(nullable id)object;
  205. /// Filters out values in the receiver that don't pass the given test.
  206. ///
  207. /// This corresponds to the `Where` method in Rx.
  208. ///
  209. /// Returns a new sequence with only those values that passed.
  210. - (RACSequence<ValueType> *)filter:(BOOL (^)(id _Nullable value))block;
  211. /// Filters out values in the receiver that equal (via -isEqual:) the provided
  212. /// value.
  213. ///
  214. /// value - The value can be `nil`, in which case it ignores `nil` values.
  215. ///
  216. /// Returns a new sequence containing only the values which did not compare
  217. /// equal to `value`.
  218. - (RACSequence *)ignore:(nullable ValueType)value;
  219. /// Unpacks each RACTuple in the receiver and maps the values to a new value.
  220. ///
  221. /// reduceBlock - The block which reduces each RACTuple's values into one value.
  222. /// It must take as many arguments as the number of tuple elements
  223. /// to process. Each argument will be an object argument. The
  224. /// return value must be an object. This argument cannot be nil.
  225. ///
  226. /// Returns a new sequence of reduced tuple values.
  227. - (RACSequence *)reduceEach:(RACReduceBlock)reduceBlock;
  228. /// Returns a sequence consisting of `value`, followed by the values in the
  229. /// receiver.
  230. - (RACSequence<ValueType> *)startWith:(nullable ValueType)value;
  231. /// Skips the first `skipCount` values in the receiver.
  232. ///
  233. /// Returns the receiver after skipping the first `skipCount` values. If
  234. /// `skipCount` is greater than the number of values in the sequence, an empty
  235. /// sequence is returned.
  236. - (RACSequence<ValueType> *)skip:(NSUInteger)skipCount;
  237. /// Returns a sequence of the first `count` values in the receiver. If `count` is
  238. /// greater than or equal to the number of values in the sequence, a sequence
  239. /// equivalent to the receiver is returned.
  240. - (RACSequence<ValueType> *)take:(NSUInteger)count;
  241. /// Zips the values in the given sequences to create RACTuples.
  242. ///
  243. /// The first value of each sequence will be combined, then the second value,
  244. /// and so forth, until at least one of the sequences is exhausted.
  245. ///
  246. /// sequences - The sequence to combine. If this collection is empty, the
  247. /// returned sequence will be empty.
  248. ///
  249. /// Returns a new sequence containing RACTuples of the zipped values from the
  250. /// sequences.
  251. + (RACSequence<RACTuple *> *)zip:(id<NSFastEnumeration>)sequence;
  252. /// Zips sequences using +zip:, then reduces the resulting tuples into a single
  253. /// value using -reduceEach:
  254. ///
  255. /// sequences - The sequences to combine. If this collection is empty, the
  256. /// returned sequence will be empty.
  257. /// reduceBlock - The block which reduces the values from all the sequences
  258. /// into one value. It must take as many arguments as the
  259. /// number of sequences given. Each argument will be an object
  260. /// argument. The return value must be an object. This argument
  261. /// must not be nil.
  262. ///
  263. /// Example:
  264. ///
  265. /// [RACSequence zip:@[ stringSequence, intSequence ]
  266. /// reduce:^(NSString *string, NSNumber *number) {
  267. /// return [NSString stringWithFormat:@"%@: %@", string, number];
  268. /// }];
  269. ///
  270. /// Returns a new sequence containing the results from each invocation of
  271. /// `reduceBlock`.
  272. + (RACSequence<ValueType> *)zip:(id<NSFastEnumeration>)sequences reduce:(RACReduceBlock)reduceBlock;
  273. /// Returns a sequence obtained by concatenating `sequences` in order.
  274. + (RACSequence<ValueType> *)concat:(id<NSFastEnumeration>)sequences;
  275. /// Combines values in the receiver from left to right using the given block.
  276. ///
  277. /// The algorithm proceeds as follows:
  278. ///
  279. /// 1. `startingValue` is passed into the block as the `running` value, and the
  280. /// first element of the receiver is passed into the block as the `next` value.
  281. /// 2. The result of the invocation is added to the returned sequence.
  282. /// 3. The result of the invocation (`running`) and the next element of the
  283. /// receiver (`next`) is passed into `block`.
  284. /// 4. Steps 2 and 3 are repeated until all values have been processed.
  285. ///
  286. /// startingValue - The value to be combined with the first element of the
  287. /// receiver. This value may be `nil`.
  288. /// reduceBlock - The block that describes how to combine values of the
  289. /// receiver. If the receiver is empty, this block will never be
  290. /// invoked. Cannot be nil.
  291. ///
  292. /// Examples
  293. ///
  294. /// RACSequence *numbers = @[ @1, @2, @3, @4 ].rac_sequence;
  295. ///
  296. /// // Contains 1, 3, 6, 10
  297. /// RACSequence *sums = [numbers scanWithStart:@0 reduce:^(NSNumber *sum, NSNumber *next) {
  298. /// return @(sum.integerValue + next.integerValue);
  299. /// }];
  300. ///
  301. /// Returns a new sequence that consists of each application of `reduceBlock`. If
  302. /// the receiver is empty, an empty sequence is returned.
  303. - (RACSequence *)scanWithStart:(nullable id)startingValue reduce:(id _Nullable (^)(id _Nullable running, ValueType _Nullable next))reduceBlock;
  304. /// Combines values in the receiver from left to right using the given block
  305. /// which also takes zero-based index of the values.
  306. ///
  307. /// startingValue - The value to be combined with the first element of the
  308. /// receiver. This value may be `nil`.
  309. /// reduceBlock - The block that describes how to combine values of the
  310. /// receiver. This block takes zero-based index value as the last
  311. /// parameter. If the receiver is empty, this block will never
  312. /// be invoked. Cannot be nil.
  313. ///
  314. /// Returns a new sequence that consists of each application of `reduceBlock`.
  315. /// If the receiver is empty, an empty sequence is returned.
  316. - (RACSequence *)scanWithStart:(nullable id)startingValue reduceWithIndex:(id _Nullable (^)(id _Nullable running, ValueType _Nullable next, NSUInteger index))reduceBlock;
  317. /// Combines each previous and current value into one object.
  318. ///
  319. /// This method is similar to -scanWithStart:reduce:, but only ever operates on
  320. /// the previous and current values (instead of the whole sequence), and does
  321. /// not pass the return value of `reduceBlock` into the next invocation of it.
  322. ///
  323. /// start - The value passed into `reduceBlock` as `previous` for the
  324. /// first value.
  325. /// reduceBlock - The block that combines the previous value and the current
  326. /// value to create the reduced value. Cannot be nil.
  327. ///
  328. /// Examples
  329. ///
  330. /// RACSequence *numbers = [@[ @1, @2, @3, @4 ].rac_sequence;
  331. ///
  332. /// // Contains 1, 3, 5, 7
  333. /// RACSequence *sums = [numbers combinePreviousWithStart:@0 reduce:^(NSNumber *previous, NSNumber *next) {
  334. /// return @(previous.integerValue + next.integerValue);
  335. /// }];
  336. ///
  337. /// Returns a new sequence consisting of the return values from each application of
  338. /// `reduceBlock`.
  339. - (RACSequence *)combinePreviousWithStart:(nullable ValueType)start reduce:(id _Nullable (^)(ValueType _Nullable previous, ValueType _Nullable current))reduceBlock;
  340. /// Takes values until the given block returns `YES`.
  341. ///
  342. /// Returns a RACSequence of the initial values in the receiver that fail
  343. /// `predicate`. If `predicate` never returns `YES`, a sequence equivalent to
  344. /// the receiver is returned.
  345. - (RACSequence<ValueType> *)takeUntilBlock:(BOOL (^)(ValueType _Nullable x))predicate;
  346. /// Takes values until the given block returns `NO`.
  347. ///
  348. /// Returns a sequence of the initial values in the receiver that pass
  349. /// `predicate`. If `predicate` never returns `NO`, a sequence equivalent to the
  350. /// receiver is returned.
  351. - (RACSequence<ValueType> *)takeWhileBlock:(BOOL (^)(ValueType _Nullable x))predicate;
  352. /// Skips values until the given block returns `YES`.
  353. ///
  354. /// Returns a sequence containing the values of the receiver that follow any
  355. /// initial values failing `predicate`. If `predicate` never returns `YES`,
  356. /// an empty sequence is returned.
  357. - (RACSequence<ValueType> *)skipUntilBlock:(BOOL (^)(ValueType _Nullable x))predicate;
  358. /// Skips values until the given block returns `NO`.
  359. ///
  360. /// Returns a sequence containing the values of the receiver that follow any
  361. /// initial values passing `predicate`. If `predicate` never returns `NO`, an
  362. /// empty sequence is returned.
  363. - (RACSequence<ValueType> *)skipWhileBlock:(BOOL (^)(ValueType _Nullable x))predicate;
  364. /// Returns a sequence of values for which -isEqual: returns NO when compared to
  365. /// the previous value.
  366. - (RACSequence<ValueType> *)distinctUntilChanged;
  367. @end
  368. NS_ASSUME_NONNULL_END