web-dev-qa-db-fra.com

Comment écrire des méthodes lambda en Objective-C?

Comment écrire des méthodes lambda en Objective-C?

66
Who knows

Le concept d'un lambda dans Objective-C est maintenant encapsulé avec l'idée de Blocks qui sont l'équivalent des fonctions de passage par référence. Bien sûr, on avait sans doute cela déjà en C avec l'idée de pointeurs de fonction; les blocs ne sont qu'un moyen de capturer également l'état local (c'est-à-dire qu'il peut s'agir de fermetures). En fait, les blocs peuvent également être utilisés dans d'autres langages C (sur Mac) - il est proposé de les intégrer à la syntaxe C standard.

Voici un exemple de définition d'un lambda pour multiplier deux nombres ensemble:

int (^mult)(int, int) = ^(int a, int b) { return a*b; };

La première partie déclare une variable, de type ^int(int,int), puis l'affecte à l'expression lambda (aka bloc) qui renvoie le multiple de ses deux arguments. Vous pouvez ensuite passer ce fn autour, le définir dans d'autres endroits, etc; vous pouvez même l'utiliser dans d'autres fonctions.

Voici un exemple de définition d'une fonction qui, lorsqu'elle est invoquée, renvoie une autre fonction:

multiplyBy = ^(int a) { return ^(int b) { return b*a; }; };
triple = multiplyBy(3);

Notez que vous pouvez mélanger des blocs avec des types d'objets (généralement en utilisant id comme type d'objet) et que la plupart des nouvelles structures de données d'objet Objective-C ont une sorte d'opération au niveau du bloc. GCD utilise également des blocs afin de transmettre des événements arbitraires; cependant, notez que GCD peut également être utilisé avec des pointeurs de fonction.

90
AlBlue

OS X 10.6 a introduit des blocs. Voir la réponse d'AlBlue pour des exemples .

Si vous n'utilisez pas Snow Leopard, vous pouvez obtenir quelque chose de proche de la composition des fonctions en utilisant diverses autres fonctionnalités.

Exemple utilisant des pointeurs de fonction C:

void sayHello() {
    NSLog(@"Hello!");
}

void doSomethingTwice(void (*something)(void)) {
    something();
    something();
}

int main(void) {
    doSomethingTwice(sayHello);
    return 0;
}

Exemple utilisant le modèle de commande:

@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;
}

Exemple d'utilisation d'un sélecteur:

@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;
}
27
Will Harris

J'ai entendu André Pang à NSConference parler de la façon dont les blocs allaient être introduits avec la prochaine version d'Objective-C.

Cela devrait permettre une programmation fonctionnelle.

Edit: Depuis la sortie de Snow Leopard, c'est effectivement le cas. Objective-C a maintenant Blocs .

3
Abizern