Saturday, May 19, 2012

Blocks (5)

Here is a last example of basic blocks in Objective-C. It comes from Mike Ash's excellent Friday Q&A about blocks. We implement the functional programming tool map as a category on NSArray.

The map method takes a block as its single argument. This is the fundamental unit of work, which in the example will operate on one element in an array of NSStrings, adding @"x" to it. The block argument to map is declared with an id argument and an id return value; these will be NSStrings when the block is defined at runtime. A different block could be fed to the same map function, and the elements wouldn't have to be strings.

map applies the block to each element of the array, storing the results in an NSMutableArray and returning it.

We use enumerateObjectsUsingBlock: to examine the values, although we could just use for (id obj in array).

// clang blocks.m -o prog -framework Foundation -fobjc-gc-only
#import <Foundation/Foundation.h>

@interface NSArray (MappingArray)
- (NSArray *)map:(id (^)(id))block;
@end;

@implementation NSArray (MappingArray)
- (NSArray *)map:(id (^)(id))block { // takes an id, returns an id
        NSMutableArray *ret = [NSMutableArray array];
        for(id obj in self)
            [ret addObject:block(obj)];
        return ret;
    }
@end

int main(int argc, char * argv[]) {
    NSArray *a, *b;
    a = [NSArray arrayWithObjects:@"a",@"b",@"c",nil];
    b = [a map:^(id obj){ return [obj stringByAppendingString:@"x"]; }];
    
    [b enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        NSLog(@"%@", obj);
        } ];
    
    return 0;
}

> ./prog
2012-05-19 10:00:13.537 prog[3426:707] ax
2012-05-19 10:00:13.539 prog[3426:707] bx
2012-05-19 10:00:13.540 prog[3426:707] cx