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
_______________________________________________
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel

Reply via email to