Objective-Cしんどい
大昔Objective-Cはサイコーだと思ってた時期はあったが、近代的な言語に触れてからだとだいぶ冗長でしんどく感じるObjective-C。
Objective-CとSwiftが混ざっているプロジェクトを触る必要があって、せめてよく使う配列操作だけでもなんとかしようと工夫してみた。
# import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSArray<__covariant ObjectType> (Functional)
@property(nonnull, readonly) void (^forEach)(void(^)(ObjectType _Nonnull object));
@property(nonnull, readonly) NSArray<ObjectType>* _Nonnull (^filter)(BOOL(^)(ObjectType _Nonnull object));
@property(nonnull, readonly) NSArray<id>* _Nonnull (^map)(id(^)(ObjectType _Nonnull object));
@property(nonnull, readonly) NSArray<id>* _Nonnull (^flatMap)(NSArray<id>* _Nonnull (^)(ObjectType _Nonnull object));
@property(nonnull, readonly) id (^reduce)(id initialValue, id (^)(id accum, ObjectType _Nonnull object));
@end
NS_ASSUME_NONNULL_END
@implementation NSArray (Functional)
-(void (^)(void (^ _Nonnull)(id _Nonnull)))forEach {
return ^(void(^block)(id)) {
for(id elem in self) block(elem);
};
}
-(NSArray<id>* _Nonnull (^)(BOOL (^ _Nonnull)(id _Nonnull)))filter {
return ^(BOOL (^blk)(id)) {
NSMutableArray<id> *arr = NSMutableArray.array;
for(id elem in self) if(blk(elem)) [arr addObject: elem];
return arr;
};
}
-(NSArray<id> * _Nonnull (^)(id (^ _Nonnull)(id _Nonnull)))map {
return ^(id(^blk)(id)) {
NSMutableArray<id> *arr = NSMutableArray.array;
for(id elem in self) [arr addObject: blk(elem)];
return arr;
};
}
-(NSArray<id> * _Nonnull (^)(NSArray<id> * _Nonnull (^ _Nonnull)(id _Nonnull)))flatMap {
return ^(NSArray<id>*(^blk)(id)) {
NSMutableArray<id> *arr = NSMutableArray.array;
for(id elem in self) [arr addObjectsFromArray: blk(elem)];
return arr;
};
}
-(id (^)(id, id (^ _Nonnull)(id, id _Nonnull)))reduce {
return ^(id initialValue, id (^blk)(id, id)) {
id accum = initialValue;
for(id elem in self) accum = blk(accum, elem);
return accum;
};
}
@end
動くか確かめる
+(void)test {
NSArray<NSNumber *>* array = @[@1, @2, @3, @4, @5, @6];
id a = array.map(^id(NSNumber * _Nonnull object) {
return @(object.intValue * 2);
});
id b = array.filter(^BOOL(NSNumber* _Nonnull object) {
return object.intValue % 2 == 0;
});
id c = array.flatMap(^NSArray<id> * _Nonnull(NSNumber* _Nonnull object) {
return @[object, object];
});
id d = array.reduce(@0, ^id _Nonnull(NSNumber* _Nonnull accum, NSNumber* _Nonnull object) {
return @(accum.intValue + object.intValue);
});
NSLog(@"%@", a);
NSLog(@"%@", b);
NSLog(@"%@", c);
NSLog(@"%@", d);
}
出力
2020-10-19 22:34:31.161505+0900 Objective-C Hacks[37672:1250661] (
2,
4,
6,
8,
10,
12
)
2020-10-19 22:34:31.161649+0900 Objective-C Hacks[37672:1250661] (
2,
4,
6
)
2020-10-19 22:34:31.161797+0900 Objective-C Hacks[37672:1250661] (
1,
1,
2,
2,
3,
3,
4,
4,
5,
5,
6,
6
)
2020-10-19 22:34:31.161942+0900 Objective-C Hacks[37672:1250661] 21
まだ極めてイケてない
これがObjective-Cの限界か?
マクロとかゴリゴリ悪用したらもっとよくならないかな。
それから配列にオブジェクトしか入らない粗末な仕様だからNSNumber入れたり出したりがダサさを際立たせてる。
こうしてみるとSwiftの型推論だとかクロージャとかがマジで記述量減らしてくれて楽。