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

Andrew Pennebaker andrew.pennebaker at gmail.com
Tue Oct 18 22:23:51 CEST 2011


Schäfer, thanks, that's a lot of practical information. Have you used
Haskell QuickCheck<http://www.haskell.org/haskellwiki/Introduction_to_QuickCheck>?
It's amazing that such a strictly typed language can do these sorts of
things.

Yes, pointers are probably the only way I can implement this, for now. If at
all possible, I'd like to use more idiomatic Pascal code. The only way I
managed to write the C port <https://github.com/mcandre/qc> was void* tricks
:P but there's only so much you can do without lambdas.

If I decide to use pointers, what's the syntax for accepting a function
pointer (unknown type, unknown arity) and calling the function? In C, you
have to know the entire function signature and explicitly cast the pointer
to that before you can call it. Does Pascal also require this, or can I just
accept a pointer and call it as if it were a normal function call?

Finally, does Pascal have syntax for something like Lisp's (apply f args),
or Smalltalk's Block valueWithArguments? Once I get forAll to accept
function pointers, and call the functions, I need a way to pass the values
to another function (again, unknown types, unknown arity).

Cheers,

Andrew Pennebaker
www.yellosoft.us

2011/10/18 Roland Schäfer <roland.schaefer at fu-berlin.de>

> 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.
> >>
> _______________________________________________
> fpc-pascal maillist  -  fpc-pascal at lists.freepascal.org
> http://lists.freepascal.org/mailman/listinfo/fpc-pascal
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/fpc-pascal/attachments/20111018/b6cd4f4a/attachment.html>


More information about the fpc-pascal mailing list