Wednesday, October 22, 2008

Exploring anonymous methods

New in Delphi 2009 are anonymous methods. Anonymous methods are methods without a name, which are able to do something on local variables where they are implemented. In fact they are a reference to a method.
Anonymous methods are a bit magic, at least they were to me, and hard to explain.
A nice place to use them is together with generics types. For instance the Sort method of a TList<T> is a natural place to use them:

PersonsList.Sort(TComparer<TPerson>.Construct(
function(const Item1, Item2: TPerson): Integer
begin
Result :
= CompareText(Item1.LastName,
Item2.LastName);
end));

A cool thing about anonymous methods is that it can execute your code (incl. local vars) in another place. This can be another unit or even another thread.

Implementing them in your daily code however is another thing. How to do that? Well here are my first explorations: Let's say we have this simple application that has a TStringList where we want to do some searching on the strings, based on the users input. I came up with this:


//Declaration of the anon reference
//The passed string will be searched on
type
TAnonStrProc
=
reference
to function(s : string) : Integer;

//Implement a method to execute
//1. Ask a string to search
//2. Execute the referenced method "proc"
function TForm4.FindString(proc: TAnonStrProc)
: Integer;
var
SearchStr : string;
begin
Result :
= -1;
if InputQuery('Search', 'Search a string',
SearchStr)
then begin
Result :
= proc(SearchStr);
end;
end;

//Create a string list
procedure TForm4.Button1Click(Sender: TObject);
var
sla : TStrings;
i,j : Integer;
Index, Count : integer;
begin
sla :
= TStringList.Create;
try
sla.Add(
'One');
sla.Add(
'Two');
sla.Add(
'Three');
sla.Add(
'Two');
//Call the FindString method with anon method
//to get the index of string in the list
//Note that it does someting with our local
//variable sla
Index := FindString(function(s : string) : Integer
begin
Result :
= sla.IndexOf(s);
end);
ShowMessage(
'Index: ' + IntToStr(Index));

//Call the FindString method with anon method
//to get the count of a searched string
Count := FindString(function(s : string) : Integer
var
str : string;
i : integer;
begin
Result :
= 0;
for str in sla do begin
if str = s then
Inc(Result);
end;
end);
ShowMessage(
'Count: ' + IntToStr(Count));
finally
sla.Free;
end;
end;

Please note that this example probably won't make it in the daily code, but it shows in a simple manner how they work. Because of the fact that our anonymouse method can take any method as long that it has a string as parameter you can call one method FindString with different implementations by passing different methods.


Well I think anonymous methods are cool. Implement them in your daily code wisely is not that simple. The working however, which seems magic at first, is after some exploring not that hard to follow.

No comments: