Delphi 2009 - Anonymous methods by Radek Červinka
Radek Červinka - 06/Jan/2010
Radek Červinka - 06/Jan/2010
[SHOWTOGROUPS=4,20]
Delphi has long had procedural types (ie, of the procedure or function type, essentially a pointer) and pointers to methods (ie, a pointer to a method). The latter is the basis of the entire VCL - whenever you declare, for example, an OnClick service, this is the second case. The first case is used less, but for example I often use it for various callback functions, etc.
Anonymous methods extend the existing state where you simply write code instead of the name of a procedure or method. In addition, the validity of local variables changes in this case.
To remind the declaration:
A simple useless example
Good isn't it? We declare the anonymous method pTest and immediately assign a piece of code to it.
Then we'll call him. But instead of calling it, we can pass it somewhere else, all you have to do is declare a method with the TAnonProc parameter, and immediately our little procedure can travel through the program - see the not-yet-tested Test2.
Local variables
Now it's time for Test2, if you uncomment her call you will get the following output:
Please note that the variable i is declared in the main program, but in Test2 it is called three times and is therefore incremented by 1 each time.
Basically, it's an extension of the old familiar embedded procedures:
The problem of parentheses
Here, as far as I know, there is the problem of parentheses when calling a method without parameters.
Similarly, if you have a function that returns an anonymous method (again, a misleading example):
So how do we call a returned function? We have these options:
Pre-prepared anonymous methods
There are several ready-made solutions in the SysUtils unit:
The TThread class has been extended by
Anonymous methods have many uses and can streamline code (but vice versa). By the way, one of the main goals was support for the future Parallel library, ie better use of multiprocessor systems in future versions.
[/SHOWTOGROUPS]
Delphi has long had procedural types (ie, of the procedure or function type, essentially a pointer) and pointers to methods (ie, a pointer to a method). The latter is the basis of the entire VCL - whenever you declare, for example, an OnClick service, this is the second case. The first case is used less, but for example I often use it for various callback functions, etc.
Anonymous methods extend the existing state where you simply write code instead of the name of a procedure or method. In addition, the validity of local variables changes in this case.
To remind the declaration:
Код:
type
TLogProc = procedure(const sText: string); // first case
TLogMethod = procedure(const sText: string) of object; // second case
TAnonProc = reference to procedure(const sText: string); // anonymous method
A simple useless example
Код:
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils,
TypInfo;
type
TAnonProc = reference to procedure(const sText: string); // anonymní metoda
procedure Test;
var
pTest: TAnonProc;
begin
pTest := procedure(const s: string)
begin
writeln(s);
end;
pTest('This is just the beginning');
pTest('And again');
pTest('Let''s eat');
end;
procedure Test2(p: TAnonProc);
begin
p('radek 1');
p('radek 2');
p('radek 3');
end;
var
i: Integer;
begin
Test;
{ Test2(
procedure (const s:string)
begin
writeln(s);
inc(i);
writeln(i);
end); }
end.
Good isn't it? We declare the anonymous method pTest and immediately assign a piece of code to it.
Then we'll call him. But instead of calling it, we can pass it somewhere else, all you have to do is declare a method with the TAnonProc parameter, and immediately our little procedure can travel through the program - see the not-yet-tested Test2.
Local variables
Now it's time for Test2, if you uncomment her call you will get the following output:
Код:
This is just the beginning
And again
I'll eat
Код:
radek 1
1
radek 2
2
radek 3
3
Please note that the variable i is declared in the main program, but in Test2 it is called three times and is therefore incremented by 1 each time.
Basically, it's an extension of the old familiar embedded procedures:
Код:
procedure test;
var
i: Integer;
//
procedure MyInc; // specialized procedure increases clarity
begin
inc(i);
end;
//
begin
i := 10;
MyInc;
MyInc;
end;
The problem of parentheses
Here, as far as I know, there is the problem of parentheses when calling a method without parameters.
Код:
type
TAnyProc = reference to procedure ;
var
AnyProc: TAnyProc;
// you need to call as AnyProc ();
// otherwise the compiler will think you want a reference and not a call
Similarly, if you have a function that returns an anonymous method (again, a misleading example):
Код:
function GetMethod: TAnonProc;
begin
Result := procedure(const s: string)
begin
ShowMessage(s);
end;
end;
So how do we call a returned function? We have these options:
Код:
var
p: TAnonProc;
begin
p:= GetMethod();
p('Hello world');
GetMethod()('Hello world');
GetMethod.Invoke('Hello world'); // Invoke added by compiler in case without parentheses
Pre-prepared anonymous methods
There are several ready-made solutions in the SysUtils unit:
Код:
type
TProc = reference to procedure;
TProc<T> = reference to procedure (Arg1: T);
TProc<T1,T2> = reference to procedure (Arg1: T1; Arg2: T2);
TProc<T1,T2,T3> = reference to procedure (Arg1: T1; Arg2: T2; Arg3: T3);
TProc<T1,T2,T3,T4> = reference to procedure (Arg1: T1; Arg2: T2; Arg3: T3; Arg4: T4);
procedure UseCode (proc: TProc);
function DoThis (proc: TProc): string;
function DoThat (procInt: TProc<Integer>): string;
type //generické typy
TFunc<TResult> = reference to function: TResult;
TFunc<T,TResult> = reference to function ( Arg1: T): TResult;
TFunc<T1,T2,TResult> = reference to function (Arg1: T1; Arg2: T2): TResult;
TFunc<T1,T2,T3,TResult> = reference to function (Arg1: T1; Arg2: T2; Arg3: T3): TResult;
TPredicate<T> = reference to function (Arg1: T): Boolean;
The TThread class has been extended by
Код:
TThreadProcedure = reference to procedure;
procedure Synchronize(AThreadProc: TThreadProcedure); overload;
Anonymous methods have many uses and can streamline code (but vice versa). By the way, one of the main goals was support for the future Parallel library, ie better use of multiprocessor systems in future versions.
[/SHOWTOGROUPS]