Skip to content

Commit

Permalink
Merge pull request #13 from kkazuo/fmap
Browse files Browse the repository at this point in the history
Fmap
  • Loading branch information
mxcl committed Dec 12, 2014
2 parents bbb5eb2 + bd6e233 commit 05f1fa2
Show file tree
Hide file tree
Showing 8 changed files with 190 additions and 2 deletions.
9 changes: 9 additions & 0 deletions NSArray+fmap.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#import "YOLO.ph"

@implementation NSArray (YOLO)

- (NSArray *(^)(id))fmap {
return self.map;
}

@end
2 changes: 1 addition & 1 deletion NSArray+map.m
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ @implementation NSArray (YOLO)
if (o)
mapped[jj++] = o;
}
return [NSArray arrayWithObjects:mapped count:jj];
return [[self.class alloc] initWithObjects:mapped count:jj];
};
}

Expand Down
32 changes: 32 additions & 0 deletions NSDictionary+fmap.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#import "YOLO.ph"

@implementation NSDictionary (YOLO)

- (NSDictionary *(^)(id))fmap {
return ^(id frock) {
NSMethodSignature *sig = YOLOMS(frock);
id (^block)(id, id) = ^{
switch (sig.numberOfArguments){
case 2: return ^(id v, id k){ return ((id(^)(id))frock)(v); };
case 3: return ^(id v, id k){ return ((id(^)(id, id))frock)(v, k); };
case 4: return ^(id v, id k){ return ((id(^)(id, id, id))frock)(v, k, self); };
default:
@throw @"Invalid argument count to fmap";
}
}();

id keys[self.count];
id objs[self.count];
int ii = 0;
for (id key in self) {
id o = block(self[key], key);
if (o) {
keys[ii] = key;
objs[ii++] = o;
}
}
return [[self.class alloc] initWithObjects:objs forKeys:keys count:ii];
};
}

@end
18 changes: 18 additions & 0 deletions NSSet+fmap.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#import "YOLO.ph"

@implementation NSSet (YOLO)

- (NSSet *(^)(id (^)(id)))fmap {
return ^(id (^block)(id)) {
id mapped[self.count];
NSUInteger ii = 0;
for (id mappable in self) {
id o = block(mappable);
if (o)
mapped[ii++] = o;
}
return [[self.class alloc] initWithObjects:mapped count:ii];
};
}

@end
1 change: 1 addition & 0 deletions YOLO-all.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#define YOLO_FIRST
#define YOLO_FLATMAP
#define YOLO_FLATTEN
#define YOLO_FMAP
#define YOLO_GET
#define YOLO_GROUPBY
#define YOLO_HAS
Expand Down
57 changes: 57 additions & 0 deletions YOLO.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,34 @@
- (NSArray *(^)(NSArray *(^)(id o)))flatMap;
#endif

#ifdef YOLO_FMAP
/**
Invokes the given block once for each element of self. Creates a new
array containing the values returned by the block.
id rv = @[@1, @2, @3, @4].fmap(^(NSNumber *n){
return @(n.intValue * n.intValue);
});
// rv => @[@1, @4, @9, @16]
If the given block returns nil, that element is skipped in the returned
array.
The given block can have up to three parameters, the first is an element
in the array, the second that element’s index, and the third the array
itself.
The second parameter can be a primitive (eg. `int`), or an `NSNumber *`:
@"YOLO".split(@"").fmap(^(NSString *letter, int index){
//…
});
@see -map
*/
- (NSArray *(^)(id block))fmap;
#endif

#ifdef YOLO_GROUPBY
/**
Groups the collection by result of the given block.
Expand Down Expand Up @@ -742,6 +770,13 @@ clear.
- (NSSet *(^)(void (^)(id o)))each;
#endif

#ifdef YOLO_FMAP
/**
@see NSArray's -fmap
*/
- (NSSet *(^)(id (^)(id obj)))fmap;
#endif

@end


Expand Down Expand Up @@ -776,6 +811,28 @@ clear.
- (NSDictionary *(^)(NSDictionary *higherPriorityDictionary))extend;
#endif

#ifdef YOLO_FMAP
/**
Invokes the given block once for each key, value pair in the receiver.
Returns a dictionary containing the values returned by the block.
id rv = @{@1: @2, @2: @4, @3: @9}.fmap(^(id obj){
return @([obj intValue] * 2);
});
// rv = @{@1: @4, @2: @8, @3: @18}
If the given block returns nil, that element is skipped in the returned
dictionary.
The given block can have up to three parameters, the first is an element
in the dictionary, the second that element’s key, and the third the dictionary
itself.
@see -map
*/
- (NSDictionary *(^)(id block))fmap;
#endif

#ifdef YOLO_GET
/**
Returns the value associated with a given key.
Expand Down
4 changes: 3 additions & 1 deletion YOLOKit.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Pod::Spec.new do |s|
ss.preserve_paths = 'YOLO.ph'
end

%w{all any array chunk concat dict each extend find first flatMap flatten get
%w{all any array chunk concat dict each extend find first flatMap flatten fmap get
groupBy has indexOf inject join last map max min none partition pick pluck
pmap pop push reduce reverse rotate sample select shift shuffle skip slice
snip sort split transpose uniq unshift upTo without
Expand All @@ -32,6 +32,8 @@ Pod::Spec.new do |s|
ss.dependency 'YOLOKit/slice'
when 'dict'
ss.dependency 'YOLOKit/transpose'
when 'fmap'
ss.dependency 'YOLOKit/map'
when 'join'
ss.dependency 'YOLOKit/pluck'
when 'reduce'
Expand Down
69 changes: 69 additions & 0 deletions tests
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,75 @@ int main() {
XCTAssertEqualObjects(aa, bb);
}
- (void)testArrayFmap {
NSArray *aaa = @[@"a", @"b", @"c", @"d"];
NSArray *aa = aaa.fmap(^(id o, uint ii, id array){
return @[o, @(ii), array];
});
id bb = @[@[@"a", @0, aaa], @[@"b", @1, aaa], @[@"c", @2, aaa], @[@"d", @3, aaa]];
XCTAssertEqualObjects(aa, bb);
XCTAssertFalse([aa isKindOfClass:[NSMutableArray class]]);
aa = @[@"a", @"b", @"c", @"d"];
bb = aa.fmap(^(id o){
return o;
});
XCTAssertEqualObjects(aa, bb);
bb = aa.fmap(^(id o, id i){
return [NSString stringWithFormat:@"%@%@", o, i];
});
aa = @[@"a0", @"b1", @"c2", @"d3"];
XCTAssertEqualObjects(aa, bb);
bb = ((NSArray *)aa.mutableCopy).fmap(^(id o) { return o; });
XCTAssertEqualObjects(aa, bb);
XCTAssertTrue([bb isKindOfClass:[NSMutableArray class]]);
}
- (void)testSetFmap {
NSSet *aa = [NSSet setWithObjects:@1, @2, @3, nil];
XCTAssertEqualObjects((aa.fmap(^(id obj) { return obj; })), aa);
XCTAssertEqualObjects((aa.fmap(^(id obj) { return (id)nil; })), [NSSet set]);
id bb = aa.fmap(^(id obj) {
return @([obj intValue] * [obj intValue]);
});
XCTAssertEqualObjects(bb, ([NSSet setWithObjects:@1, @4, @9, nil]));
XCTAssertFalse([bb isKindOfClass:[NSMutableSet class]]);
bb = ((NSSet *)aa.mutableCopy).fmap(^(id obj) {
return @([obj intValue] * [obj intValue]);
});
XCTAssertEqualObjects(bb, ([NSSet setWithObjects:@1, @4, @9, nil]));
XCTAssertTrue([bb isKindOfClass:[NSMutableSet class]]);
}
- (void)testDictionaryFmap {
XCTAssertEqualObjects(@{}, (@{}.fmap(^(id obj) { return obj; })));
NSDictionary *aa = @{@1: @2, @2: @4, @3: @9};
XCTAssertEqualObjects(aa, (aa.fmap(^(id obj) { return obj; })));
id bb = aa.fmap(^(id obj){
return @([obj intValue] * 2);
});
XCTAssertEqualObjects(bb, (@{@1: @4, @2: @8, @3: @18}));
XCTAssertFalse([bb isKindOfClass:[NSMutableDictionary class]]);
bb = aa.fmap(^(id obj, id key){
return @([obj intValue] * 2 + [key intValue]);
});
XCTAssertEqualObjects(bb, (@{@1: @5, @2: @10, @3: @21}));
bb = ((NSDictionary *)aa.mutableCopy).fmap(^(id obj){
return @([obj intValue] * 2);
});
XCTAssertEqualObjects(bb, (@{@1: @4, @2: @8, @3: @18}));
XCTAssertTrue([bb isKindOfClass:[NSMutableDictionary class]]);
}
- (void)testPick {
NSDictionary *a = @{@1: @2, @2: @3, @3: @4};
id b = a.pick(@1, @2, @5, nil);
Expand Down

0 comments on commit 05f1fa2

Please sign in to comment.