[fpc-pascal] Closures (or anonymous functions)

Anthony Walter sysrpl at gmail.com
Sun Jan 3 15:46:46 CET 2010


I'll just repeat what I said in the FPC 2.4.0 release thread.

* See the good news note at the bottom of this message

Something I've really found useful in C#/.NET is lambda functions and
capturing locals (closures). This feature solves asynchronous design
for me in so many ways. If you can follow the code at the bottom of
this reply, and note how url and dimension locals are captured.

IMO, the key to asynchronous programming usability is be able to wrap
up a calls neatly. Lambda functions allow for delayed execution of
arbitrary strongly typed methods/functions. More so than anonymous
methods, because you may omit the tedious and unnecessary work of
defining callback signatures and saving parameters.

With a simple declaration such as "delegate object Task();" I can
capture any method imaginable as a lambda. If I want to download and
resize images in a background thread, I simply use a lambda to declare
"() => Download.BitmapScaled(url, scale)". This is converted to a
variable of type Task. The Task BitmapScaled returns an Bitmap (or
Exception) object which can then be accessed in the Complete callback
as result under the context of the main thread. Nothing could be
better IMO.

Something to note about this form of lambda, it depends on a unified
type system. That is to say, a model where all things derive from a
single base object (classes, records, events, etc).

// inside a static class called Async ...
public delegate object Task();
public delegate void Complete(object result);
public static void Execute(Task task, Complete complete) { ... }

Which can then lead to code like this:

downloading = true;
progressControl.Status = ProgressStatus.Busy;
Async.Execute(() => Download.BitmapScaled(url, scale), DownloadComplete);

... and in DownloadComplete:

private void DownloadComplete(object result)
{
 downloading = false;
 progressControl.Status = ProgressStatus.None;
 if (result is Exception)
   progressControl.Text = "An error occurred during download";
 else
 {
   progressControl.Text = String.Empty;
   imageControl.Image = result as Bitmap;
 }
}

The good news is: Yesterday I managed to squeeze some of this into
Delphi 7 in a hacked sort of way.



More information about the fpc-pascal mailing list