新感覚アドベントカレンダー、LL/ML Advent Calendar 2012 (#LLAdventJP) の13日目
Objective-Cを書いているとどうしても長くなってしまうので、Scalaくらい短く書きたい。というわけでいろいろな方法を使って短くしたいと思います、FizzBuzzを。
理想
1 to 100 map { i => (i%3, i%5) match { case (0, 0) => "FizzBuzz" case (0, _) => "Fizz" case (_, 0) => "Buzz" case _ => i.toString } } foreach println
Objective-Cだと普通はこんなかんじでしょう
for (NSInteger i = 1 ; i <= 100; i ++) { if (i % 15 == 0) { NSLog(@"FizzBuzz"); } else if (i % 3 == 0) { NSLog(@"Fizz"); } else if (i % 5 == 0) { NSLog(@"Buzz"); } else { NSLog(@"%d", i); } }
NSLogが複数あるのを一つにする。@(i)でNSNumberのObjectにすることができる。
NSIntegerが長いので省略
typedef NSInteger Int; for (Int i = 1 ; i <= 100; i ++) { NSLog(@"%@", (i % 15 == 0)? @"FizzBuzz" : (i % 3 == 0)? @"Fizz" : (i % 5 == 0)? @"Buzz" : [@(i) stringValue] ); }
Categoryという機能を使って既存のclassにメソッドを追加することができます。
NSArrayにmapとforeachのmethodを追加します。
@interface NSArray (Fanctional) - (NSArray *(^)(id (^)(id)))map; - (void (^)(void (^func)(id)))foreach; @end @implementation NSArray (Fanctional) - (NSArray *(^)(id (^func)(id)))map { return ^(id (^func)(id)){ NSMutableArray *array = [NSMutableArray array]; for (Int i = 0, _len = [self count]; i < _len; i++) { array[i] = func(self[i]); } return array; }; } - (void (^)(void (^)(id)))foreach { return ^(void (^func)(id)){ for (Int i = 0, _len = [self count]; i < _len; i++) { func(self[i]); } }; } @end
NSMutableArray *ma = [NSMutableArray new]; for (Int i = 0 ; i < 100; i ++) { ma[i] = @(i + 1); } ma.map(^(id n) { Int i = [n integerValue]; return (i % 15 == 0)? @"FizzBuzz" : (i % 3 == 0)? @"Fizz" : (i % 5 == 0)? @"Buzz" : [@(i) stringValue]; }).foreach(^(id s){NSLog(@"%@",s);});
NSNumbarにtoメソッドを追加する
@interface NSNumber (Fanctional) - (NSArray *(^)(Int))to; @end @implementation NSNumber (Fanctional) - (NSArray *(^)(Int))to { return ^(Int to){ NSMutableArray *ma = [NSMutableArray array]; Int i = 0, from = [self integerValue]; to -= from; for (; i <= to ; i++) { ma[i] = @(i + from); } return ma; }; } @end
@(1).to(100).map(^(id n) { Int i = [n integerValue]; return (i % 15 == 0)? @"FizzBuzz" : (i % 3 == 0)? @"Fizz" : (i % 5 == 0)? @"Buzz" : [@(i) stringValue]; }).foreach(^(id s){NSLog(@"%@",s);});
パターンマッチを実装したいところですが、すでに13日がなくなっているのでこの辺にしておきます。
そもそも理想が間違ってるとかいうな