Delphi Programming

and software in general.

Saturday, August 2, 2008

Anonymous Methods - When to use them?

As many others, I am still trying to wrap my head around this. All the hubbub about anon.methods, but lack of direct descriptions of actual use, lead us to take a "Emperor's New Clothes" kind of view on them.

I believe there are some areas where anon.methods will have a significant impact. Not dramatic or revolutionary - but significant.

That said, we do really need something solid which demonstrate the advantages of anon.methods beyond the trivial one-liner demo methods (which easily can be done in the "old ways"). Until we see some, here is some speculation and conjecture from my side...

1. Lambda expressions and Generics
I assume that for generic classes, the compiler generates something to the effect of anon.methods behind the scene. I also assume that anon.methods are one of the building blocks in type inference.

2. Isolation Glue
When you write classes that interact in the traditional OOP way, you often have to derive new classes from the base classes and implement a set of features (read: method override) where you apply your knowledge of the two new classes to create new interaction rules. Very often, such override methods are just a handful of lines. Yet you have to add yet another two classes to achieve it. In concept, this is a similar problem domain to generics - but here we could be talking about trying to make two specific classes (such as a visual and a non-visual) work together without having to reimplement all the plumbing in great explicitness.

Anon.methods can simplify this by allowing one of the classes to implement all the glue using anon.methods instead of having to implement overridden virtual methods in both classes.

3. Threads
Threads today are a fairly elaborate construction project. Anon.methods may enable us to create something similar to fibers. Where the old style single kernel fibers had to deal with manual scheduling on one CPU, today's multi-core aware fiber management code can delegate the "packaged" anon.methods and data (or fibers if you like) to multiple kernels for actual concurrency.

In what way will this differ from threads? Threads are elaborate to design, requiring yet another class descendant to implement the Execute method. You have to manually feed them their data/scope, and manually retrieve any generated content, and manually implement a "tie it all together" sync.point (ie where you are waiting for all threads to complete so that you can continue). They are expensive to set up, kick off and there is a lot of housekeeping involved.

From the top of my head, here are some forms of processing can be compartmentalized using anon.methods without the overhead of multiple thread class implementations: Sorting (key generation/comparison), matrix math / SSD type processing like compression/decompression, and other types of algoritmic code. In theory, any sequential processing that don't have backwards or forwards dependencies in the dataset, would be trivial to parallelize.

The result should be less obstacles to writing code that actually can utilize all your hardware.

• Is it possible to do this with the existing TThread? Yes it is.
• Can anon.methods reduce the complexity of doing it? Most likely, yes.

• Is it is still possible to do horrific mistakes? Yes, but they are the same old mistakes as for regular threads (race, starve, deadlock, data you can't/shouldn't touch, etc), and since you are now defining your thread/fiber in the scope of it's deployer - it may be that the compiler can make more intelligent judgement about the validity of your thread/fiber.

Will anon.methods lead to spaghetti?
I don't think so. Generally speaking, they may make some things clearer as more of the logic can be packed into one class, instead of being spread over multiple related classes. All "generic" code (pardon the pun) can be kept simple and ..ehm.. generic, and you don't have to build a huge inheritance tree where methods are virtualized up the wazzoo.

I think a possible factor in explaining why it is hard to come up with examples that are short, detailed and easily understood, is that we will benefit the most from anonymous methods in code that is anything but trivial.

P.S. In Bart Roozendaal's blog about anon.methods, Thomas Mueller mentions that the good old Turbo Pascal TCollection ForEach and FirstThat will be possible again. That's not a bad example either. I actually missed those a lot when I couldn't use them anymore.

Edit: Make sure to read Jarle Stabell's article on Lambda functions!

Edit 2:
• An older post from Barry Kelly on how how closures presents a challenge in Delphi for Win32. I guess we know by now that they landed on refcounting.
• The "Pascal gets Closures before Java" Reddit thread.

Edit 3:
Wayne Niddery on Understanding Anonymous Methods
Jolyon Smith on Anonymous Methods - When should they be used?
Andreano Lanusse - Tiburon - Anonymous Methods

Edit 4: • Joel Spolsky - Can your programming language do this?