[fpc-pascal] Re: Delphi's anonymous functions in Free Pascal

Lukasz Sokol el.es.cr at gmail.com
Tue Oct 18 10:57:53 CEST 2011


On 17/10/2011 21:53, Andrew Pennebaker wrote:
> Does Free Pascal have anonymous functions that you can pass around,
> e.g. to a sort(compare : function, arr : array) function?
> 
> If not, does anyone know any hacks to accomplish this?
> 
> Cheers,
> 
> Andrew Pennebaker www.yellosoft.us <http://www.yellosoft.us>
> 

Yes:

//you can declare a type :

TMyFunction: function(AMyParam : TType): TOtherType;

// then implement:

function MyFunctionWithArbitraryName(AMyParam: TType): TOtherType;
begin
  {do something with AMyParam}
end;

//then (or before, if the TMyFunction is in type declaration section)

function AFunctionUsingTMyFunctionAsArgument(AFunction : TMyFunction):TWhateverType;
var OtherReturn: TOtherType;
    AParameterToAFunction : TType;
begin
  {some code}
  OtherReturn := AFunction(AParameter);  
  {other code}
end;

// and finally even
const   MYFUNCTIONCOUNT = 1
	ArrayOfTMyFunction = array[0..MYFUNCTIONCOUNT-1] of TMyFunction = (MyFunctionWithArbitraryName);
						{it's a static array, so match the number of elemets}

begin
  for {declared somewhere global} i := 0 to MYFUNCTIONCOUNT-1 do
    WhateverReturn := AFunctionUsingTMyFunctionAsArgument(ArrayOfTMyFunction[i](MyParam));
   
end.

(Terms and conditions : this is invoked from /dev/mem, some syntax discrepancies may occur
as my attention moved on from this as it obviously worked)

I have written a dumb CLI interpreter this way ;) recently.
(the function table contains command name as string in a record together with the function 
and the main procedure looks for the name and executes the arbitrary function when found)

TMyFunctionRecord = record
  CLIName: string;
  MyFunction : TMyFunction
end;

const ArrayOfCLIFunctions = array[0..CLIFUNCCOUNT-1] of TMyFunctionRecord = ({...});

var CLIFunctionToExecute : TMyFunction;
    WhateverReturn : TWhateverType;

begin
  for i := 0 to CLIFUNCCOUNT-1 do 
    if ArrayOfCLIFunctions[i].CLIName = paramstr[1] then
      begin
        CLIFunctionToExecute := ArrayOfCLIFunctions[i].MyFunction;
        break;
      end;
  WhateverReturn := AFunctionUsingTMyFunctionAsArgument(CLIFunctionToExecute(MyParam));
end.


Also the 'anonymous' functions can be implemented in a separate unit which only exports the
/relevant/ ones in its interface section.

The obvious limitation / safeguard is : you must use the function of declared type to pass into
the function AFunctionUsingTMyFunctionAsArgument(AFunction : TMyFunction) and no other type;
(An obvious workaround to that is to use varargs ;) but I did not try that so I can't tell
whether that would work)

It's not much OOP in action (and may have {obvious for some //not me} performance penalties but oh well. ;)

L.




More information about the fpc-pascal mailing list