views:

1156

answers:

3

How to write lambda methods in Objective-C ?

+10  A: 

OS X 10.6 introduced blocks. See AlBlue's answer for examples.

If you're not using Snow Leopard, you can get something close to function composition using various other features.

Example using C function pointers:

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

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

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

Example using the command pattern:

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

Example using a selector:

@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;
}
Will Harris
This may have been true earlier, but the language now does have Blocks, which allow you to define real lambda expressions. Having said that, being able to pass around @selector()s as described above is a really useful mechanism in the Objective-C toolkit.
AlBlue
-1 for missing info about blocks, a central new feature, available in C, ObjC and C++, when using Apple's GCC in the new 10.6 version of OS X.
harms
+2  A: 

I heard André Pang at NSConference talking about how blocks were going to be introduced with the next version of Objective-C.

This should allow functional programming.

Edit: Since Snow Leopard has been released, this is indeed the case. Objective-C now has Blocks.

Abizern
+16  A: 

The concept of a lambda in Objective-C is now encapsulated with the idea of Blocks which are the equivalent of pass-by-reference functions. Of course, arguably one had that already in C with the idea of function pointers; blocks are just a way of also capturing local state (i.e. can be closures). In fact, blocks can also be used in other C languages as well (on Mac) - there's a proposal to make them part of the standard C syntax.

Here's an example of defining a lambda to multiply two numbers together:

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

The first part declares a variable, of type ^int(int,int) and then assigns it to the lambda expression (aka block) which returns the multiple of its two arguments. You can then pass that fn around, define it in other places etc; you can even use it in other functions.

Here's an example of defining a function, which when invoked, returns another function:

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

Note that you can intermix blocks with object types (usually using id as the object type) and many of the new Objective-C object data structures have some kind of block-level operation. GCD also uses blocks in order to pass in arbitrary events; however, note that GCD can also be used with function pointers as well.

AlBlue
+1 for a detailed answer.
Abizern
Note also that block support has been ported to 10.5 and the iPhone OS with the Plausible Blocks project. http://code.google.com/p/plblocks/
Chuck