[fpc-pascal] Caller agnostic procedure variables

Ryan Joseph genericptr at gmail.com
Tue Feb 15 08:06:15 CET 2022


This has been a constant problem for me with FPC and wanted to make a formal post with code examples since I've only mentioned it in passing before.

How can it be achieved to have a caller agnostic procedure variables? I've tried making some big crazy dispatch record that uses generics but because generics don't support variable templates (like some languages have TClass<T...>) it was limited and clunky to use.

The problem is that from the perspective of the receiver it shouldn't really care what the caller has provided except for that there is a procedure that needs to be called. For example if there is a "sort" function that takes a procedure variable it shouldn't care if the procedure is a global function, a method or a nested function (and eventually a closure).

It feels like the compiler needs a new type which encapsulates these different types but I'm not sure how this all works internally. Any thoughts on this?

===========================

{$mode objfpc}

program procvars;

type
  TMyAction = procedure;
  TMyClass = class
    procedure MyAction;
  end;

procedure DoThis(action: TMyAction);
  begin
    action();
  end;

procedure MyAction;
  begin
  end;

procedure Test;
  
  procedure MyNestedAction; 
  begin
  end;

  var
    c: TMyClass;
  begin
    // of object
    c := TMyClass.Create;
    DoThis(@c.MyAction); // error: Incompatible type for arg no. 1: Got "<procedure variable type of procedure of object;Register>", expected "<procedure variable type of procedure;Register>"

    // is nested
    DoThis(@MyNestedAction); // error: Incompatible type for arg no. 1: Got "<procedure variable type of procedure is nested;Register>", expected "<procedure variable type of procedure;Register>"

    // normal
    DoThis(@MyAction);
  end;

begin

end.

Regards,
	Ryan Joseph



More information about the fpc-pascal mailing list