I propose that the support for https://en.wikipedia.org/wiki/Function_object be added to the FPC.
A subset of such functionality already existed as a part of my implementation of closures, so I extended that part to implement the core feature for allowing functors -- overloading of the call operator: when round brackets are applied to an instance of a record, object/class, or interface type, they are translated into a call to the method Invoke of that instance. The attached proof-of-concept functors-1.patch allows the following test case to be compiled: -------8<-------
type I = interface
procedure Invoke;end;
type C = class(TInterfacedObject, I)
class function Invoke(const N: Integer): Integer; overload;
procedure Invoke; overload;
end;
class function C.Invoke(const N: Integer): Integer;
begin
result := N + 9
end;
procedure C.Invoke;
begin
writeln(ClassName, '.Invoke')
end;
type H = class helper for C
procedure Invoke(const S: string); overload;
end;
procedure H.Invoke(const S: string);
begin
writeln('H.Invoke("', S, '")')
end;
var aC: C;
var anI: I;
begin
aC := C.Create;
writeln( aC(33) );
aC('hello');
anI := aC;
anI()
end.
-------8<-------
Important design points:
1) Applying round brackets to instances does not collide with the existing syntax;
2) Naturally, helpers are able to turn helpees into functors;
3) Operator () cannot be applied to types -- that would clash with explicit type conversions;
4) Explicit empty argument lists are required -- unorthogonal to routines and procedural variables, but clarity must win here;
5) {$modeswitch Closures} is required (modeswitch_closures.patch from https://lists.freepascal.org/pipermail/fpc-devel/2021-December/044261.html) -- functors are closure-adjacent in the area of functional programming.
The parts that are currently missing:
1) Implicit conversion from functors to method pointers -- should be fairly trivial to implement;
2) Support for generics -- should be straightforward as well;
3) The OPERATOR keyword instead of PROCEDURE/FUNCTION for methods Invoke -- should we choose to require it -- would be somewhat more complicated.