Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2023-03

Working with anonymous functions

2 messages · 2 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Thomas Kurz

Dear all,

I'm testing FPC-trunk and I'm especially interested in using anonymous functions because they should simplify working with TThread.Synchronize and others a lot.

I stumbled upon an issue which I'd like to post here first because I am not sure whether it's a bug or just a wrong usage on my side.

Here's a small example:

program project1;
{$modeswitch anonymousfunctions}
{$modeswitch functionreferences}
uses Classes, EventLog, SysUtils;
type
  TTest = class
    FOnLog: TLogMessageEvent;
    procedure CallOnLog (AEventType: TEventType; AMessage: String);
  end;
procedure TTest.CallOnLog (AEventType: TEventType; AMessage: String);
var
  r: reference to TThreadMethod = nil;
  m: TThreadMethod = nil;
begin
  // This doesn't work because the anonymous procedure is
  // capturing local symbols. I understand that this doesn't work.
  m := procedure
    begin
      FOnLog (Self, AEventType, AMessage);
    end;
  // As far as I have understood
  // https://forum.lazarus.freepascal.org/index.php/topic,59468.0.html
  // the solution should be to use a "reference to".
  // In fact, assignment works as expected:
  r := procedure
    begin
      FOnLog (Self, AEventType, AMessage);
    end;
  // But I seem not to have any change to pass the reference.
  // Both versions fail:
  TThread.ForceQueue (NIL, r());
  TThread.ForceQueue (NIL, @r);
end;
begin
end.

As you can see, the goal is to call TThread.ForceQueue. Of course, the easiest solution was having an overloaded "TThread.ForceQueue (TThread, TThreadProcedure)" as is the case with Delphi. I have already posted a feature request on Github.

But I don't know why I can't use a "reference to TThreadMethod". If I understand the feature announcement correctly, this should work, shouldn't it?

Kind regards,
Thomas

Sven Barth
to Thomas Kurz
Thomas Kurz wrote 26 lines
Dear all, I'm testing FPC-trunk and I'm especially interested in using anonymous functions because they should simplify working with TThread.Synchronize and others a lot. I stumbled upon an issue which I'd like to post here first because I am not sure whether it's a bug or just a wrong usage on my side. Here's a small example: program project1; {$modeswitch anonymousfunctions} {$modeswitch functionreferences} uses Classes, EventLog, SysUtils; type TTest = class FOnLog: TLogMessageEvent; procedure CallOnLog (AEventType: TEventType; AMessage: String); end; procedure TTest.CallOnLog (AEventType: TEventType; AMessage: String); var r: reference to TThreadMethod = nil;

/That/ should not compile. The correct syntax is "reference to function ..." or "reference to procedure ...".

And the type you're looking for is "TThreadProcedure" which is declared as "reference to procedure".

Show quoted text 30 lines
m: TThreadMethod = nil; begin // This doesn't work because the anonymous procedure is // capturing local symbols. I understand that this doesn't work. m := procedure begin FOnLog (Self, AEventType, AMessage); end; // As far as I have understood // https://forum.lazarus.freepascal.org/index.php/topic,59468.0.html // the solution should be to use a "reference to". // In fact, assignment works as expected: r := procedure begin FOnLog (Self, AEventType, AMessage); end; // But I seem not to have any change to pass the reference. // Both versions fail: TThread.ForceQueue (NIL, r()); TThread.ForceQueue (NIL, @r); end; begin end. As you can see, the goal is to call TThread.ForceQueue. Of course, the easiest solution was having an overloaded "TThread.ForceQueue (TThread, TThreadProcedure)" as is the case with Delphi. I have already posted a feature request on Github.

I've added the overload.

But I don't know why I can't use a "reference to TThreadMethod". If I understand the feature announcement correctly, this should work, shouldn't it?

That declaration is nonsense, so no, that should definitely not work.

Regards,
Sven