いまさらながらObjective-CでBlocksってみたが、これはおもしろい。
まずは無名関数を使用。もともとgccには入れ子関数があったけど、必要な場所で定義できるのはすごく便利:
void foo(NSArray *array)
{
^(id x){ NSLog(@"%@", x); }(array);
}
クロージャなので、こういう風にも書ける:
void foo(NSArray *array)
{
^(){ NSLog(@"%@", array); }();
}
無名関数は引数にできる。って、これができなきゃ無名関数の意味がない:
void bar(void (^f)(id), id x)
{
f(x);
}
void foo(NSArray *array)
{
bar(^(id x){ NSLog(@"%@", x); }, array);
}
もちろん、クロージャも引数になる:
void bar(void (^f)())
{
f();
}
void foo(NSArray *array)
{
bar(^(){ NSLog(@"%@", array); });
}
無名関数は戻り値にもなる:
void (^bar())(id)
{
return ^(id x){ NSLog(@"%@", x); };
}
void foo(NSArray *array)
{
bar()(array);
}
しかし、クロージャを戻り値にするとコンパイル時にエラーになる:
void (^bar(id x))()
{
return ^(){ NSLog(@"%@", x); };
}
void foo(NSArray *array)
{
bar(array)();
}
元はC言語なんで、このへんが限界か。 と思ったが、 Block_copy() で環境を保存できるらしい:
#import <Block.h>
void (^bar(id x))()
{
return Block_copy(^(){ NSLog(@"%@", x);});
}
void foo(NSArray *array)
{
void (^f)() = bar(array);
f();
Block_release(f);
}
でも、なんか美しくないなぁ。無名なのが利点の一つなのに、名前をつけなきゃいけないなんて…