在 objective-c 上玩玩函数式编程
2017-12-27 本文已影响78人
MarkNote
tags:ios
每一个iOS开发者都有很多纠结的事。即使对老手而言也是如此。每做一个新的 feature 都要纠结一下是用 obj-c 还是 swift 来写。这种纠结随着 swift 的成熟而与日俱增。
技术选型犹如采购电子产品,用新不用旧,新项目自然倾向于用 swift 。无奈手头的应用有很多基于 obj-c ,不可能完全重写。而 obj-c 与 swift 混编虽然可行,却不是我想走的方向。一来无端的给应用增加了一些不必要的东西,二来频繁在 obj-c 与 swift 之间来回切换给心灵带来的冲击实在太大,毕竟二者的范式不同。
如此看来,让基于 obj-c 的开发更舒坦一点是很有意义的。swift 的若干语言特性中,对函数式编程编程的友好支持是让人心动的。其实在 obj-c 中,也可以做到类似的效果。有一些第三方的库,比如RXCollections,可以在这方面帮我们。然而我不太喜欢RXCollections中方法的命名。 自己简单的整了一下,可以愉快的玩玩了。
头文件声明
#import <Foundation/Foundation.h>
@interface NSArray (FP)
- (NSArray *)filter:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate;
- (NSArray *) sort:( NSComparisonResult (^)(id obj1, id obj2)) block;
- (NSArray *)map:(id(^)(id))block;
- (id) reduce:(id (^)(id memo, id obj)) block withInitialMemo:(id) memo;
@end
实现文件
#import "NSArray+FP.h"
@implementation NSArray (FP)
- (NSArray *)filter:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate {
NSIndexSet * filteredIndexes = [self indexesOfObjectsPassingTest:predicate];
return [self objectsAtIndexes:filteredIndexes];
}
- (NSArray *)map:(id(^)(id))block {
NSMutableArray * newArray = [NSMutableArray array];
for (id item in self) {
id obj = block(item);
[newArray addObject:obj];
}
NSArray *arrReturn = [NSArray arrayWithArray:newArray];
[newArray removeAllObjects];
return arrReturn;
}
- (NSArray *) sort:( NSComparisonResult (^)(id obj1, id obj2)) block {
return [self sortedArrayUsingComparator:block];
}
- (id) reduce:(id (^)(id memo, id obj)) block withInitialMemo:(id) memo {
for (id obj in self) {
memo = block(memo, obj);
}
return memo;
}
@end
使用
filter
NSArray * allRemovedRecords = [allRecords filter:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
CKRecord *record = (CKRecord *) obj;
//NSString *filename = [self generateFileName:record];
if(record[@"status"] && [kRemoved isEqualToString:record[@"status"]]){
return YES;
} else {
return NO;
}
}];
map
return [files map:^id(id item) {
NSString * fileName = (NSString *) item;
return [fileName stringByDeletingPathExtension];
}];
sort
NSArray *sortedKeys = [[tags allKeys] sort:^NSComparisonResult(id a, id b) {
NSString *s1 = (NSString *) a;
NSString *s2 = (NSString *) b;
if([s1 isEqualToString:T(@"All")]){
return -1;
} else if([s2 isEqualToString:T(@"All")]){
return 1;
} else {
return [a compare:b];
}
}];
总结
以上通过对 NSArray 做的category 为例,实现了filter,sort,map,reduce 等高阶函数,可以减少循环的使用,同时让代码变得整洁。