Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redeclare operations built on RACStream primitives with more precise type information (continued) #41

Merged
merged 1 commit into from
Nov 20, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 0 additions & 16 deletions ReactiveObjC.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -2874,10 +2874,6 @@
baseConfigurationReference = D047263219E49FE8006002AA /* iOS-Application.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
);
INFOPLIST_FILE = ReactiveObjCTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(PROJECT_NAME)Tests";
Expand All @@ -2889,10 +2885,6 @@
baseConfigurationReference = D047263219E49FE8006002AA /* iOS-Application.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
);
INFOPLIST_FILE = ReactiveObjCTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(PROJECT_NAME)Tests";
Expand Down Expand Up @@ -2967,10 +2959,6 @@
baseConfigurationReference = D047263219E49FE8006002AA /* iOS-Application.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
);
INFOPLIST_FILE = ReactiveObjCTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(PROJECT_NAME)Tests";
Expand Down Expand Up @@ -3045,10 +3033,6 @@
baseConfigurationReference = D047263219E49FE8006002AA /* iOS-Application.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
);
INFOPLIST_FILE = ReactiveObjCTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(PROJECT_NAME)Tests";
Expand Down
2 changes: 1 addition & 1 deletion ReactiveObjC/RACArraySequence.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@

// Returns a sequence for enumerating over the given array, starting from the
// given offset. The array will be copied to prevent mutation.
+ (instancetype)sequenceWithArray:(NSArray *)array offset:(NSUInteger)offset;
+ (RACSequence *)sequenceWithArray:(NSArray *)array offset:(NSUInteger)offset;

@end
2 changes: 1 addition & 1 deletion ReactiveObjC/RACArraySequence.m
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ @implementation RACArraySequence

#pragma mark Lifecycle

+ (instancetype)sequenceWithArray:(NSArray *)array offset:(NSUInteger)offset {
+ (RACSequence *)sequenceWithArray:(NSArray *)array offset:(NSUInteger)offset {
NSCParameterAssert(offset <= array.count);

if (offset == array.count) return self.empty;
Expand Down
6 changes: 3 additions & 3 deletions ReactiveObjC/RACEagerSequence.m
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ @implementation RACEagerSequence

#pragma mark RACStream

+ (instancetype)return:(id)value {
+ (RACSequence *)return:(id)value {
return [[self sequenceWithArray:@[ value ] offset:0] setNameWithFormat:@"+return: %@", RACDescription(value)];
}

- (instancetype)bind:(RACStreamBindBlock (^)(void))block {
- (RACSequence *)bind:(RACSequenceBindBlock (^)(void))block {
NSCParameterAssert(block != nil);
RACStreamBindBlock bindBlock = block();
NSArray *currentArray = self.array;
Expand All @@ -39,7 +39,7 @@ - (instancetype)bind:(RACStreamBindBlock (^)(void))block {
return [[self.class sequenceWithArray:resultArray offset:0] setNameWithFormat:@"[%@] -bind:", self.name];
}

- (instancetype)concat:(RACSequence *)sequence {
- (RACSequence *)concat:(RACSequence *)sequence {
NSCParameterAssert(sequence != nil);
NSCParameterAssert([sequence isKindOfClass:RACSequence.class]);

Expand Down
2 changes: 2 additions & 0 deletions ReactiveObjC/RACEmptySequence.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@
// Private class representing an empty sequence.
@interface RACEmptySequence : RACSequence

+ (RACEmptySequence *)empty;

@end
2 changes: 1 addition & 1 deletion ReactiveObjC/RACIndexSetSequence.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@
// Private class that adapts an array to the RACSequence interface.
@interface RACIndexSetSequence : RACSequence

+ (instancetype)sequenceWithIndexSet:(NSIndexSet *)indexSet;
+ (RACSequence *)sequenceWithIndexSet:(NSIndexSet *)indexSet;

@end
2 changes: 1 addition & 1 deletion ReactiveObjC/RACIndexSetSequence.m
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ @implementation RACIndexSetSequence

#pragma mark Lifecycle

+ (instancetype)sequenceWithIndexSet:(NSIndexSet *)indexSet {
+ (RACSequence *)sequenceWithIndexSet:(NSIndexSet *)indexSet {
NSUInteger count = indexSet.count;

if (count == 0) return self.empty;
Expand Down
266 changes: 266 additions & 0 deletions ReactiveObjC/RACSequence.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,4 +149,270 @@ NS_ASSUME_NONNULL_BEGIN

@end

/// A block which accepts a value from a RACSequence and returns a new sequence.
///
/// Setting `stop` to `YES` will cause the bind to terminate after the returned
/// value. Returning `nil` will result in immediate termination.
typedef RACSequence * _Nullable (^RACSequenceBindBlock)(id _Nullable value, BOOL *stop);

@interface RACSequence (RACStream)

/// Returns a sequence that immediately sends the given value and then completes.
+ (RACSequence *)return:(nullable)value;

/// Returns a sequence that immediately completes.
+ (RACSequence *)empty;

/// Lazily binds a block to the values in the receiver.
///
/// This should only be used if you need to terminate the bind early, or close
/// over some state. -flattenMap: is more appropriate for all other cases.
///
/// block - A block returning a RACSequenceBindBlock. This block will be invoked
/// each time the bound sequence is re-evaluated. This block must not be
/// nil or return nil.
///
/// Returns a new sequence which represents the combined result of all lazy
/// applications of `block`.
- (RACSequence *)bind:(RACSequenceBindBlock (^)(void))block;

/// Subscribes to `sequence` when the source sequence completes.
- (RACSequence *)concat:(RACSequence *)sequence;

/// Zips the values in the receiver with those of the given sequence to create
/// RACTuples.
///
/// The first `next` of each sequence will be combined, then the second `next`,
/// and so forth, until either sequence completes or errors.
///
/// sequence - The sequence to zip with. This must not be `nil`.
///
/// Returns a new sequence of RACTuples, representing the combined values of the
/// two sequences. Any error from one of the original sequence will be forwarded
/// on the returned sequence.
- (RACSequence *)zipWith:(RACSequence *)sequence;

@end

/// Redeclarations of operations built on the RACStream primitives with more
/// precise type information.
@interface RACSequence (RACStreamOperations)

/// Maps `block` across the values in the receiver and flattens the result.
///
/// Note that operators applied _after_ -flattenMap: behave differently from
/// operators _within_ -flattenMap:. See the Examples section below.
///
/// This corresponds to the `SelectMany` method in Rx.
///
/// block - A block which accepts the values in the receiver and returns a new
/// instance of the receiver's class. Returning `nil` from this block is
/// equivalent to returning an empty sequence.
///
/// Returns a new sequence which represents the combined sequences resulting
/// from mapping `block`.
- (RACSequence *)flattenMap:(__kindof RACSequence * _Nullable (^)(id _Nullable value))block;

/// Flattens a sequence of sequences.
///
/// This corresponds to the `Merge` method in Rx.
///
/// Returns a sequence consisting of the combined sequences obtained from the
/// receiver.
- (RACSequence *)flatten;

/// Maps `block` across the values in the receiver.
///
/// This corresponds to the `Select` method in Rx.
///
/// Returns a new sequence with the mapped values.
- (RACSequence *)map:(id _Nullable (^)(id _Nullable value))block;

/// Replaces each value in the receiver with the given object.
///
/// Returns a new sequence which includes the given object once for each value in
/// the receiver.
- (RACSequence *)mapReplace:(nullable id)object;

/// Filters out values in the receiver that don't pass the given test.
///
/// This corresponds to the `Where` method in Rx.
///
/// Returns a new sequence with only those values that passed.
- (RACSequence *)filter:(BOOL (^)(id _Nullable value))block;

/// Filters out values in the receiver that equal (via -isEqual:) the provided
/// value.
///
/// value - The value can be `nil`, in which case it ignores `nil` values.
///
/// Returns a new sequence containing only the values which did not compare
/// equal to `value`.
- (RACSequence *)ignore:(nullable id)value;

/// Unpacks each RACTuple in the receiver and maps the values to a new value.
///
/// reduceBlock - The block which reduces each RACTuple's values into one value.
/// It must take as many arguments as the number of tuple elements
/// to process. Each argument will be an object argument. The
/// return value must be an object. This argument cannot be nil.
///
/// Returns a new sequence of reduced tuple values.
- (RACSequence *)reduceEach:(id _Nullable (^)())reduceBlock;

/// Returns a sequence consisting of `value`, followed by the values in the
/// receiver.
- (RACSequence *)startWith:(nullable id)value;

/// Skips the first `skipCount` values in the receiver.
///
/// Returns the receiver after skipping the first `skipCount` values. If
/// `skipCount` is greater than the number of values in the sequence, an empty
/// sequence is returned.
- (RACSequence *)skip:(NSUInteger)skipCount;

/// Returns a sequence of the first `count` values in the receiver. If `count` is
/// greater than or equal to the number of values in the sequence, a sequence
/// equivalent to the receiver is returned.
- (RACSequence *)take:(NSUInteger)count;

/// Zips the values in the given sequences to create RACTuples.
///
/// The first value of each sequence will be combined, then the second value,
/// and so forth, until at least one of the sequences is exhausted.
///
/// sequences - The sequence to combine. If this collection is empty, the
/// returned sequence will be empty.
///
/// Returns a new sequence containing RACTuples of the zipped values from the
/// sequences.
+ (RACSequence *)zip:(id<NSFastEnumeration>)sequence;

/// Zips sequences using +zip:, then reduces the resulting tuples into a single
/// value using -reduceEach:
///
/// sequences - The sequences to combine. If this collection is empty, the
/// returned sequence will be empty.
/// reduceBlock - The block which reduces the values from all the sequences
/// into one value. It must take as many arguments as the
/// number of sequences given. Each argument will be an object
/// argument. The return value must be an object. This argument
/// must not be nil.
///
/// Example:
///
/// [RACSequence zip:@[ stringSequence, intSequence ]
/// reduce:^(NSString *string, NSNumber *number) {
/// return [NSString stringWithFormat:@"%@: %@", string, number];
/// }];
///
/// Returns a new sequence containing the results from each invocation of
/// `reduceBlock`.
+ (RACSequence *)zip:(id<NSFastEnumeration>)sequences reduce:(id _Nullable (^)())reduceBlock;

/// Returns a sequence obtained by concatenating `sequences` in order.
+ (RACSequence *)concat:(id<NSFastEnumeration>)sequences;

/// Combines values in the receiver from left to right using the given block.
///
/// The algorithm proceeds as follows:
///
/// 1. `startingValue` is passed into the block as the `running` value, and the
/// first element of the receiver is passed into the block as the `next` value.
/// 2. The result of the invocation is added to the returned sequence.
/// 3. The result of the invocation (`running`) and the next element of the
/// receiver (`next`) is passed into `block`.
/// 4. Steps 2 and 3 are repeated until all values have been processed.
///
/// startingValue - The value to be combined with the first element of the
/// receiver. This value may be `nil`.
/// reduceBlock - The block that describes how to combine values of the
/// receiver. If the receiver is empty, this block will never be
/// invoked. Cannot be nil.
///
/// Examples
///
/// RACSequence *numbers = @[ @1, @2, @3, @4 ].rac_sequence;
///
/// // Contains 1, 3, 6, 10
/// RACSequence *sums = [numbers scanWithStart:@0 reduce:^(NSNumber *sum, NSNumber *next) {
/// return @(sum.integerValue + next.integerValue);
/// }];
///
/// Returns a new sequence that consists of each application of `reduceBlock`. If
/// the receiver is empty, an empty sequence is returned.
- (RACSequence *)scanWithStart:(nullable id)startingValue reduce:(id _Nullable (^)(id _Nullable running, id _Nullable next))reduceBlock;

/// Combines values in the receiver from left to right using the given block
/// which also takes zero-based index of the values.
///
/// startingValue - The value to be combined with the first element of the
/// receiver. This value may be `nil`.
/// reduceBlock - The block that describes how to combine values of the
/// receiver. This block takes zero-based index value as the last
/// parameter. If the receiver is empty, this block will never
/// be invoked. Cannot be nil.
///
/// Returns a new sequence that consists of each application of `reduceBlock`.
/// If the receiver is empty, an empty sequence is returned.
- (RACSequence *)scanWithStart:(nullable id)startingValue reduceWithIndex:(id _Nullable (^)(id _Nullable running, id _Nullable next, NSUInteger index))reduceBlock;

/// Combines each previous and current value into one object.
///
/// This method is similar to -scanWithStart:reduce:, but only ever operates on
/// the previous and current values (instead of the whole sequence), and does
/// not pass the return value of `reduceBlock` into the next invocation of it.
///
/// start - The value passed into `reduceBlock` as `previous` for the
/// first value.
/// reduceBlock - The block that combines the previous value and the current
/// value to create the reduced value. Cannot be nil.
///
/// Examples
///
/// RACSequence *numbers = [@[ @1, @2, @3, @4 ].rac_sequence;
///
/// // Contains 1, 3, 5, 7
/// RACSequence *sums = [numbers combinePreviousWithStart:@0 reduce:^(NSNumber *previous, NSNumber *next) {
/// return @(previous.integerValue + next.integerValue);
/// }];
///
/// Returns a new sequence consisting of the return values from each application of
/// `reduceBlock`.
- (RACSequence *)combinePreviousWithStart:(nullable id)start reduce:(id _Nullable (^)(id _Nullable previous, id _Nullable current))reduceBlock;

/// Takes values until the given block returns `YES`.
///
/// Returns a RACSequence of the initial values in the receiver that fail
/// `predicate`. If `predicate` never returns `YES`, a sequence equivalent to
/// the receiver is returned.
- (RACSequence *)takeUntilBlock:(BOOL (^)(id _Nullable x))predicate;

/// Takes values until the given block returns `NO`.
///
/// Returns a sequence of the initial values in the receiver that pass
/// `predicate`. If `predicate` never returns `NO`, a sequence equivalent to the
/// receiver is returned.
- (RACSequence *)takeWhileBlock:(BOOL (^)(id _Nullable x))predicate;

/// Skips values until the given block returns `YES`.
///
/// Returns a sequence containing the values of the receiver that follow any
/// initial values failing `predicate`. If `predicate` never returns `YES`,
/// an empty sequence is returned.
- (RACSequence *)skipUntilBlock:(BOOL (^)(id _Nullable x))predicate;

/// Skips values until the given block returns `NO`.
///
/// Returns a sequence containing the values of the receiver that follow any
/// initial values passing `predicate`. If `predicate` never returns `NO`, an
/// empty sequence is returned.
- (RACSequence *)skipWhileBlock:(BOOL (^)(id _Nullable x))predicate;

/// Returns a sequence of values for which -isEqual: returns NO when compared to
/// the previous value.
- (RACSequence *)distinctUntilChanged;

@end

NS_ASSUME_NONNULL_END
Loading