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.

_______________________________________________
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply via email to