Blocks/Closures For C!

Chris Lattner, of Apple’s compiler team, writes :

Until there is more real documentation, this is a basic idea of Blocks: it is closures for C. It lets you pass around units of computation that can be executed later. For example:

void call_a_block(void (^blockptr)(int)) {
blockptr(4);
}

void test() {
int X = ...
call_a_block(^(int y){ print(X+y); });  // references stack var
snapshot

call_a_block(^(int y){ print(y*y); });
}

In this example, when the first block is formed, it snapshots the value of X into the block and builds a small structure on the stack. Passing the block pointer down to call_a_block passes a pointer to this stack object. Invoking a block (with function call syntax) loads the relevant info out of the struct and calls it. call_a_block can obviously be passed different blocks as long as they have the same type.

This is very exciting: it’s the kind of new abstraction the C family has needed for years. As you know if you’ve worked in Ruby or Python or Smalltalk or any functional language, the ability to declare an anonymous function inline, and pass it as a parameter to another function, opens the door to creating new and useful control structures. Blocks are to control structures as struct is to data structures.

For example, one of the things that blew my mind about Smalltalk-80 when I first learned it was how the basic conditional and loop operations were not hardwired into the language; instead, they were just methods of built-in classes. For example:

root := y>=0 ifTrue: [y sqrt] ifFalse: [-1]

(Apologies if I’ve messed up the syntax; it’s been a long time.) Yes, this is an if-then-else expression. But literally, it’s the message ifTrue:ifFalse: being sent to the (boolean) result of the expression y>0, with its parameters being two blocks. And what happens at runtime is that the class True implements ifTrue:ifFalse: by evaluating the first block parameter and returning its value, while the class False implements it by evaluating the second block.

This is, not surprisingly, a bit too expensive a way to implement the ubiquitous if-then-else, so in practice the compiler optimizes this expression into hardwired bytecodes instead. But it demonstrates that you can define comparable control structures yourself for your own purposes … such as for URL routing in a web application, which many Ruby and Python frameworks allow to be customized with blocks.

I think blocks will also make it possible to implement better concurrency patterns like Actors in a clean way. You may recall that I was investigating these, but after a few days I gave up because the necessary stack munging confused the Obj-C runtime too much. Once blocks are available (and hopefully integrated into Objective-C and Foundation) I’ll have to give it another try.

Previously: Career update
Next Post: Web Apps Need More UI, Not Less