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

Roland Schäfer roland.schaefer at fu-berlin.de
Tue Oct 18 21:27:32 CEST 2011


On 10/18/2011 8:10 PM, Andrew Pennebaker wrote:
> Sokol, I'm writing a function GenArray(generator) that returns a random
> array populated by calling the generator function. So the return type of
> GenArray matches "array of" the return type of the generator function, for
> any generator function.
> 
> E.g., GenArray(GenChar) would return a random string. (Except I don't know
> the syntax for passing function pointers.)

Sven pointed out yesterday that you cannot achieve in FPC what you want
to achieve. (I haven't used Delphi in a long time and don't know what
exactly anonymous functions are in Delphi, but I strongly tend to trust
his word.) You can't get anonymous but only typed "function pointers"
(cf. also Lukasz mail, second to last paragraph, plus his short mail).

Since you were asking for hacks... By way of satire(!): To bypass the
need to explicitly define a function type for each data type, you could
give up on types and write a lot of functions like

function GenChar : Pointer;
function GenString : Pointer;

The type of all of those can be given as

type TGen = function : Pointer;

Generator would have to return an array of Pointer in this scenario.
Then, you could hack your way on from there. Please don't mention my
name, though.

However, if you're just asking about the syntax for procedural types,
the "Language reference guide" for FPC 2.4.4, section 3.6 (p. 45) has
all the details: http://www.freepascal.org/docs.var

> Maybe you could fork my code 

Out of curiosity: Is that the impersonal "you"?

> and use templates to achieve this?

Generics are currently for classes only, as chapter 8 (p. 87) of the
aforementioned reference guide explains.

Best,
Roland

> On Tue, Oct 18, 2011 at 4:57 AM, Lukasz Sokol <el.es.cr at gmail.com> wrote:
> 
>> 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