Blocked-C
Update: It appears that the original article has been removed, and has been superseded by material at: http://developer.apple.com/mac/articles/cocoa/introblocksgcd.html. The original article had more on the Cocoa block APIs and gave a refreshingly honest assessment of the for-loop vs. Block-iteration comparison.
As you can see, the version using blocks is very, very noisy, both syntactically and semantically, especially compared with the HOM version:
No prizes for guessing which I'd prefer. To put some numbers on my preference: 234 characters vs. 52, 19 tokens vs. 3, 5 lines vs. 1. In fact, even a plain old C for-loop is more compact and less noisy than our "modern" blocked version:
While the news that Apple is adding blocks to C and Objective-C in the SnowLeopard time frame has been around for some time, a recent article shed some light on the actual API.
While there probably are some places where Objective-C blocks can be useful, I am not really impressed. In the following samples, red is used to show noise, meaning code that is just there to make the compiler happy.
NSMutableArray *filteredItems= [NSMutableArray array];
[items enumerateObjectsWithOptions:0 withBlock:
^(id item, NSUInteger index, BOOL *stop) {
[filteredItems addObject:[item stringByAppendingString:@"suffix"]];
}
];
As you can see, the version using blocks is very, very noisy, both syntactically and semantically, especially compared with the HOM version:
[[items collect] stringByAppendingString:@"suffix"];
No prizes for guessing which I'd prefer. To put some numbers on my preference: 234 characters vs. 52, 19 tokens vs. 3, 5 lines vs. 1. In fact, even a plain old C for-loop is more compact and less noisy than our "modern" blocked version:
NSMutableArray *filteredItems= [NSMutableArray array];
for (int i=0; i < [items count]; i++ ) {
[filteredItems addObject:[items objectAtIndex:i] stringByAppendingString:@"suffix"];
}
];
Labels: Blocks, Cocoa, Higher Order Messaging

3 Comments:
But your example is not completely fair… from my (Smalltalk) experience, the block passed to #collect: is often not a single message send, but rather a small adhoc expression, for which it does not really make sense to define a named method. Or you might need both the element and its key/index… how does HOM deal with that?
Damien: this is a valid point that I have actually thought about quite a bit...probably worth another post.
Aren't you just arguing against the API and possibly the syntax, rather than the concept of first-class closures?
A proper API would support:
NSArray *new = [items map: ^(id item) {
return [id stringByAppendingString: @"suffix"];
}];
An improved, type-inferring syntax would support something like:
val new = [items map i =>[i stringByAppendingString: @"suffix"]];
As an earlier commenter noted, single message sends are unusual, and generally speaking you'll want a broader expression. That it's to say that HOM isn't valuable, but I don't see why it's an either/or proposition.
Additionally, if you can't see more than "some" places blocks are useful and you're not impressed, you just aren't looking very hard.
Apple's closure syntax may not be the best, but you very easily can model quite a few complex ideas on top of them -- lazily, recursively evaluated sequences, simple sequence comprehensions, futures ...
Post a Comment
<< Home