[fpc-devel] Delphi anonymous methods
Sven Barth
pascaldragon at googlemail.com
Mon Mar 4 14:29:28 CET 2013
Am 04.03.2013 01:15, schrieb Graeme Geldenhuys:
> On 2013-03-02 19:03, vrt277 wrote:
>> I want to implement support of Delphi anonymous methods for fpc.
>
> Just curious... why must such a feature be allowed in Object Pascal?
> Referring to the recent "butchering of the Object Pascal language"
> thread we had recently in fpc-pascal.
You should not look only at the syntax (after all I'm not a big fan of
the syntax either, but I definitely support the feature). Look behind it
and see what it provides. The most important concept of anonymous
functions is the closure concept. That the function can capture the
content of local variables and extend their lifetime past the lifetime
of the function where it was originally defined.
E.g. (and please ignore the syntax!)
=== example begin ===
type
TMyFunc = reference to function(aArg: Integer): String;
function GetFunction: TMyFunc;
var
someintf: ISomeInterface;
s: String;
begin
someintf := TSomeInterfaceImpl.Create;
s := someintf.GetSomeString;
Result := function(aArg: Integer): String
begin
Result := someintf.SomeFunc(aArg) + s;
end;
end;
// somewhere else
var
f: TMyFunc;
begin
f := GetFunction;
Writeln(f(42));
end;
=== example end ===
The "s" and the "someintf" will exist until the "f" variable goes out of
scope ("reference to" procvars use rerence counting).
Also in the context of threading anonymous methods can be considered a
nice alternative. First there is the point of Synchronize:
The way that currently needs to be done with FPC and older Delphi versions:
=== example begin ===
type
TMyThread = class(TThread)
private
fAddText: String;
procedure AddTextSync;
protected
procedure Execute; override;
end;
procedure TMyThread.AddTextSync;
begin
// normally one should use an event or something, but we'll just
directly access the GUI here
fMyForm.Memo.Lines.Add(fAddText);
end;
procedure TMyThread.Execute;
begin
//...
fAddText := 'Step 42';
Synchronize(@AddTextSync);
//...
end;
=== example end ===
With anonymous functions:
=== example begin ===
type
TMyThread = class(TThread)
protected
procedure Execute; override;
end;
procedure TMyThread.Execute;
begin
//...
Synchronize(
procedure
begin
fMyForm.Memo.Lines.Add('Step 42');
end;
);
//...
end;
=== example end ===
With the proposed lambda syntax from another recent thread:
=== example begin ===
type
TMyThread = class(TThread)
protected
procedure Execute; override;
end;
procedure TMyThread.Execute;
begin
//...
Synchronize(lambda TProc as fMyForm.Memo.Lines.Add('Step 42'));
//...
end;
=== example end ===
Also the new extensions of the TThread-API brought another nice gimmick:
=== example begin ===
// fire and forget something :)
TThread.CreateAnonymousThread(procedure
begin
SomeThingThatShouldBeDoneParallel;
end
).Start;
=== example end ===
Some of the things could be implemented by allowing "is nested" procvars
additionally to normal procvars or "of object" procvars (e.g. for
TThread.Synchronize and TThread.Queue). But what is not trivially to
implement with current features of FPC is the closure aspect. The
resulting code would more ugly than even a really fat anonymous function.
Again: I'm not a supporter of the anonynmous function syntax. But I
support the semantic behind it. Which is why I wanted to have closures
supported through nested functions/procedures in non-Delphi modes. [And
I'd also like a lambda syntax for simple cases, e.g. one
statement/expression]
Regards,
Sven
More information about the fpc-devel
mailing list