Objective-Cでラムダメソッドを記述する方法
Objective-Cのラムダの概念は、参照渡し関数に相当する Blocks の概念でカプセル化されています。もちろん、おそらく、Cには関数ポインタの概念を持つものがあります。ブロックは、ローカル状態をキャプチャするための単なる方法です(つまり、クロージャにすることができます)。実際、ブロックは他のC言語でも使用できます(Macの場合)-標準のC構文の一部にすることを提案しています。
2つの数値を乗算するラムダを定義する例を次に示します。
_int (^mult)(int, int) = ^(int a, int b) { return a*b; };
_
最初の部分は^int(int,int)
型の変数を宣言し、2つの引数の倍数を返すラムダ式(別名ブロック)に割り当てます。その後、そのfnを渡したり、他の場所で定義したりできます。他の機能で使用することもできます。
以下は、呼び出されたときに別の関数を返す関数を定義する例です。
_multiplyBy = ^(int a) { return ^(int b) { return b*a; }; };
triple = multiplyBy(3);
_
ブロックをオブジェクトタイプと混在させることができ(通常はオブジェクトタイプとしてid
を使用)、新しいObjective-Cオブジェクトデータ構造の多くには、ある種のブロックレベルの操作があります。 GCDはまた、任意のイベントを渡すためにブロックを使用します。ただし、GCDは関数ポインターでも使用できることに注意してください。
OS X 10.6で導入されたブロック。 例についてはAlBlueの回答 を参照してください。
Snow Leopardを使用していない場合は、他のさまざまな機能を使用して、機能構成に近いものを取得できます。
C関数ポインターの使用例:
void sayHello() {
NSLog(@"Hello!");
}
void doSomethingTwice(void (*something)(void)) {
something();
something();
}
int main(void) {
doSomethingTwice(sayHello);
return 0;
}
コマンドパターンの使用例:
@protocol Command <NSObject>
- (void) doSomething;
@end
@interface SayHello : NSObject <Command> {
}
@end
@implementation SayHello
- (void) doSomething {
NSLog(@"Hello!");
}
@end
void doSomethingTwice(id<Command> command) {
[command doSomething];
[command doSomething];
}
int main(void) {
SayHello* sayHello = [[SayHello alloc] init];
doSomethingTwice(sayHello);
[sayHello release];
return 0;
}
セレクターの使用例:
@interface SaySomething : NSObject {
}
- (void) sayHello;
@end
@implementation SaySomething
- (void) sayHello {
NSLog(@"Hello!");
}
@end
void doSomethingTwice(id<NSObject> obj, SEL selector) {
[obj performSelector:selector];
[obj performSelector:selector];
}
int main(void) {
SaySomething* saySomething = [[SaySomething alloc] init];
doSomethingTwice(saySomething, @selector(sayHello));
[saySomething release];
return 0;
}
NSConferenceのAndréPangが、Objective-Cの次のバージョンでどのようにブロックが導入されるかについて話しているのを聞いた。
これにより、関数型プログラミングが可能になります。
編集:Snow Leopardがリリースされたので、これは確かにそうです。 Objective-Cに Blocks が追加されました。