Last week's build of Elements, .2447, brings a major new language feature that I personally am very excited about to Oxygene, and also as a language extension to our RemObjects C# dialect: trailing closures.
What are trailing closures?
Let's start with some background. Many APIs you work with every day take some kind of callback as last parameter. This could be APIs that perform a long operation asynchronously, or perform an action in a specific context, or repeatedly.
Traditionally you would either have to pass the name of a separate method or, using slightly more modern paradigms, a lambda function or an anonynous method (a.k.a. closure) to provide that callback. But while that works well, anonymous methods still look awkward and bulky. You have the begin
/end
pair inside the parenthesis for the method call, which looks awkward, and all the extra boilerplate of the anon declaration.
Trailing closures take the callback code out of the parenthesis of the method call, and transfer the API into something feels a lot more like a language primitive such as if ... then begin ... end
than a nested method. For example, consider this call to dispatch_async
, a common API on the Cocoa platform:
dispatch_async(myQueue) begin
PerformSlowWorkInBackground;
end;
Doesn't this look much nicer than the equivalent with an anonymous method? It feels as if dispatch_async
is a natural extension of the language, not some awkward API. And the callback code feels like it's part of the core body of your code.
The same works in C#:
dispatch_async(myQueue)
{
PerformSlowWorkInBckground();
}
And of course Swift has had trailing closures from day one as part of the standard language spec. In fact, that's where we nicked the idea from.
Why Trailing Closures and Why Now?
The main reason we implemented trailing closures is in service of a much larger and more exciting feature that we're working on for 2020 but isn't quite ready to be talked about. But we believe they will come in very handy in day-to-day work in Oxygene and C# for almost everybody right away.
For me personally, the main codebase I live and breathe every day is Fire/Water, and if I would have to guess, that code contains more methods that do use a callback or two than ones that don't. While I won't go in and change all the existing code that works, within minutes of working on something in the Fire codebase, I was able to enjoy the new feature this week — and the new code looks so much cleaner as a result.
Read More
You can read more about trailing closures in the docs for Oxygene and C#. And make sure to grab build .2447, out on the Preview channel now, to check the feature out for yourself.
You might also want to read about await
-able callbacks, here.