Как написать лямбда-методы в Objective-C? - PullRequest
65 голосов
/ 03 июня 2009

Как писать лямбда-методы в Objective-C?

Ответы [ 3 ]

88 голосов
/ 27 ноября 2009

Концепция лямбды в Objective-C теперь заключена в идею блоков , которые эквивалентны функциям передачи по ссылке. Конечно, возможно, это уже было в C с идеей указателей на функции; блоки - это просто способ захвата локального состояния (т. е. могут быть замыкания). Фактически, блоки могут также использоваться в других языках C (на Mac) - есть предложение сделать их частью стандартного синтаксиса C.

Вот пример определения лямбды для умножения двух чисел:

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

Первая часть объявляет переменную типа ^int(int,int), а затем присваивает ее лямбда-выражению (так называемому блоку), которое возвращает кратное двух ее аргументов. Затем вы можете передать этот fn, определить его в других местах и ​​т. Д .; Вы даже можете использовать его в других функциях.

Вот пример определения функции, которая при вызове возвращает другую функцию:

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

Обратите внимание, что вы можете смешивать блоки с типами объектов (обычно используя id в качестве типа объекта), и многие из новых структур данных объектов Objective-C имеют своего рода операции на уровне блоков. GCD также использует блоки для передачи произвольных событий; однако учтите, что GCD также можно использовать с указателями функций.

27 голосов
/ 03 июня 2009

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;
}
3 голосов
/ 03 июня 2009

Я слышал, как Андре Пан в NSConference говорил о том, как блоки будут введены в следующей версии Objective-C.

Это должно позволить функциональное программирование.

Редактировать: Поскольку Snow Leopard был выпущен, это действительно так. Objective-C теперь имеет блоков .

...