Delphi's anonymous functions in Free Pascal

classic Classic list List threaded Threaded
125 messages Options
1234 ... 7
Reply | Threaded
Open this post in threaded view
|

Delphi's anonymous functions in Free Pascal

Andrew Pennebaker
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

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Delphi's anonymous functions in Free Pascal

Sven Barth-2
Am 17.10.2011 22:53, schrieb Andrew Pennebaker:
> 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?

No, FPC does not support this currently and I know no one who plans to
support it in the near future.

A similiar feature available in the upcoming 2.6 and in trunk are
"nested function references". I wrote about that some days ago in this
mail: http://www.hu.freepascal.org/lists/fpc-pascal/2011-October/030460.html

Regards,
Sven

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Delphi's anonymous functions in Free Pascal

el_es
In reply to this post by Andrew Pennebaker
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  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Delphi's anonymous functions in Free Pascal

el_es
[...]
(facepalm)
I did not try 'anonymous' function as you asked, oh. Need to learn to read ;)

L.

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Delphi's anonymous functions in Free Pascal

Andrew Pennebaker
In reply to this post by el_es
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.)

Maybe you could fork my code and use templates to achieve this?


Cheers,

Andrew Pennebaker

On Tue, Oct 18, 2011 at 4:57 AM, Lukasz Sokol <[hidden email]> 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  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Delphi's anonymous functions in Free Pascal

Roland Schäfer
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 <[hidden email]> 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  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Delphi's anonymous functions in Free Pascal

Alberto Narduzzi
In reply to this post by Andrew Pennebaker
anonimous types, thrice, generic array concatenation, interpreting
Pascal, anonymous functions...

I'm guessing what language you come from.

Then, the second question arises: why Pascal, now.


Anyway, I think that immersing yourself in some classes and pointer
logic could help you find some solutions to your tasks.
(I still, anyway, suggest the quick and dirty C way with its macros and
includes...)

Cheers, A.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Delphi's anonymous functions in Free Pascal

Sven Barth-2
In reply to this post by Roland Schäfer
On 18.10.2011 21:27, Roland Schäfer wrote:
> 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).

For anonymous functions you can take a look at Embarcadero's Delphi help
here:
http://docwiki.embarcadero.com/RADStudio/en/Anonymous_Methods_in_Delphi

Regards,
Sven
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Delphi's anonymous functions in Free Pascal

Andrew Pennebaker
In reply to this post by Roland Schäfer
Schäfer, thanks, that's a lot of practical information. Have you used Haskell 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 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

2011/10/18 Roland Schäfer <[hidden email]>
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 <[hidden email]> 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  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Delphi's anonymous functions in Free Pascal

Roland Schäfer
On 10/18/2011 10:23 PM, Andrew Pennebaker wrote:
> Schäfer, thanks, that's a lot of practical information. Have you used
> Haskell QuickCheck

In fact, I have, but I don't see the connection.

> 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.

Those sentences form a contradiction.

> but there's only so much you can do without lambdas.

I saw the l-word coming.

> If I decide to use pointers,

... you'll end up on CodeSOD.

> what's the syntax for accepting a function
> pointer (unknown type, unknown arity) and calling the function? In C, you

In Pascal, you use procedural type variables, not function pointers; it
makes a conceptual and a practical difference. Procedural type variables
have a type (hence the name). You can push them around as untyped
Pointers, but you shouldn't. My *joke* was about turning the result type
of your functions into Pointer, so all your GenSomething functions are
of the same procedural type and can thus be accepted as an argument by
your generator... with virtually unusable results. Please, RTM.

> 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?

If you read the aforementioned reference and meditate about it, you
might notice why you don't have to cast procedural type variables in Pascal.

Regards,
Roland
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Delphi's anonymous functions in Free Pascal

Andrew Pennebaker
The procedural types doc is informative, thanks for the suggestion.

Eh, much humor will be lost on me. I'm a Pascal newbie, so if you suggest function pointers, even with (satire!) comments, that's what I'll use. Pointers do the job in C, why shouldn't they in Pascal?

There are CodeSOD hacks, and there are necessary hacks. If you don't like the void* trickery in qc, issue a pull request.

Cheers,

Andrew Pennebaker

2011/10/18 Roland Schäfer <[hidden email]>
On 10/18/2011 10:23 PM, Andrew Pennebaker wrote:
> Schäfer, thanks, that's a lot of practical information. Have you used
> Haskell QuickCheck

In fact, I have, but I don't see the connection.

> 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.

Those sentences form a contradiction.

> but there's only so much you can do without lambdas.

I saw the l-word coming.

> If I decide to use pointers,

... you'll end up on CodeSOD.

> what's the syntax for accepting a function
> pointer (unknown type, unknown arity) and calling the function? In C, you

In Pascal, you use procedural type variables, not function pointers; it
makes a conceptual and a practical difference. Procedural type variables
have a type (hence the name). You can push them around as untyped
Pointers, but you shouldn't. My *joke* was about turning the result type
of your functions into Pointer, so all your GenSomething functions are
of the same procedural type and can thus be accepted as an argument by
your generator... with virtually unusable results. Please, RTM.

> 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?

If you read the aforementioned reference and meditate about it, you
might notice why you don't have to cast procedural type variables in Pascal.

Regards,
Roland


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Delphi's anonymous functions in Free Pascal

Michael Fuchs-5
In reply to this post by Sven Barth-2
Am 18.10.2011 21:42, schrieb Sven Barth:
> For anonymous functions you can take a look at Embarcadero's Delphi help
> here:
> http://docwiki.embarcadero.com/RADStudio/en/Anonymous_Methods_in_Delphi

The Embarcadero style of anonymous functions does not satify me.

   myFunc := function(x, y: Integer): Integer
   begin
     Result := x + y;
   end;

This is not easier than writing:

   function Bla(x, y: Integer): Integer
   begin
     Result := x + y;
   end;

   myfunc := @Bla;


I would prefer a style like

   myfunc := @function(x, y: Integer): Integer Result := x + y;

But this makes it hard to read. Of course it would be nice to have
anonymous functions or even lambdas (think about integrated languages
like LinQ). But maybe Pascals strength of easy readable code gets lost.

Michael
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Delphi's anonymous functions in Free Pascal

Sven Barth-2
Am 19.10.2011 09:31, schrieb Michael Fuchs:
> I would prefer a style like
>
> myfunc := @function(x, y: Integer): Integer Result := x + y;

And how would you create more complex functions? In Pascal code blocks
are started with "begin" and ended with "end". I don't see a reason why
anonymous methods should differ here.

Also the example given by Embarcadero is a bit boring. The interesting
thing about anonymous methods (and nested functions types in FPC) is
that they can access variables of the surrounding function (at least I
hope that I've understand it correctly that nested function types can do
that).

E.g.

TIntegerFunc = reference to function: Integer;

procedure SomeOtherProc(aFunc: TIntegerFunc);
...

procedure Foo;
var
   x: Integer;
begin
   x := 42;
   SomeOtherProc(function: Integer; begin Result := x; end;);
end;

I haven't tested that, but from the description that should work.

The FPC equivalent should be (not tested as well):

type
   TIntegerFunc = function: Integer is nested;

procedure SomeOtherProc(aFunc: TIntegerFunc);
...

procedure Foo;
var
   x: Integer;

   function ReturnX: Integer;
   begin
     Result := x;
   end;

begin
   x := 42;
   SomeOtherProc(@ReturnX);
end;

Regards,
Sven
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Delphi's anonymous functions in Free Pascal

el_es
In reply to this post by Andrew Pennebaker
Hi Andrew,
first of all my /first/ name is Lukasz. Would you /like/ me to use your
surname to refer to yourself ?

Second you seem to be sending the same message twice in one post (once as
plain text the other as HTML) and quoted/printable encoding to make matters
even worse. Please teach your (gmail ?) to behave.

Third you're top-posting and this is is a no-no to many;
  We're not your corporate friends who are on top of things by definition,
  we have our lives and we read from the beginning to refresh on the matter.

Fourth, you're leaving too much of the quote below your answer, for what exactly?
  Save electrons, they are becoming scarce.
 
Fourth and I won't go into technicalities here but what is it exactly you
want to achieve by trying to make FPC bend over backwards ?

L.

On 18/10/2011 19:10, Andrew Pennebaker wrote:
[...cut quote...]

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Delphi's anonymous functions in Free Pascal

Michael Fuchs-5
In reply to this post by Sven Barth-2
Am 19.10.2011 10:16, schrieb Sven Barth:
>> I would prefer a style like
>>
>> myfunc := @function(x, y: Integer): Integer Result := x + y;
>
> And how would you create more complex functions? In Pascal code blocks
> are started with "begin" and ended with "end". I don't see a reason why
> anonymous methods should differ here.

Allow both, like it is already allowed in Pascal:

   if True then DoSomething;

   if True then begin
     DoSomething;
     DoSomethingMore;
     Etc;
   end;

If a function only contains one statement it is not a codeblock.

Michael


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Delphi's anonymous functions in Free Pascal

Alexander Shishkin
In reply to this post by Sven Barth-2
19.10.2011 12:16, Sven Barth пишет:

> E.g.
>
> TIntegerFunc = reference to function: Integer;
>
> procedure SomeOtherProc(aFunc: TIntegerFunc);
> ...
>
> procedure Foo;
> var
> x: Integer;
> begin
> x := 42;
> SomeOtherProc(function: Integer; begin Result := x; end;);
> end;
>
> I haven't tested that, but from the description that should work.
>
> The FPC equivalent should be (not tested as well):
>
> type
> TIntegerFunc = function: Integer is nested;
>
> procedure SomeOtherProc(aFunc: TIntegerFunc);
> ...
>
> procedure Foo;
> var
> x: Integer;
>
> function ReturnX: Integer;
> begin
> Result := x;
> end;
>
> begin
> x := 42;
> SomeOtherProc(@ReturnX);
> end;
>
> Regards,
> Sven
> _______________________________________________
> fpc-pascal maillist - [hidden email]
> http://lists.freepascal.org/mailman/listinfo/fpc-pascal
>
>

But _real_ functional equivalent of Delphi's function reference if
COM-interface based functor.
F.e.
"TMyFuction = reference to function: Integer; "
and
"IMyFunction = interface
     function Invoke:Integer;
end;"




_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Delphi's anonymous functions in Free Pascal

leledumbo
Administrator
Hmm... I'm not really sure though, but I guess you could make use of "array of const" feature. See the documentation here: http://www.freepascal.org/docs-html/ref/refsu60.html
Reply | Threaded
Open this post in threaded view
|

Re: Delphi's anonymous functions in Free Pascal

Florian Klämpfl
In reply to this post by Sven Barth-2
Am 19.10.2011 10:16, schrieb Sven Barth:

> Am 19.10.2011 09:31, schrieb Michael Fuchs:
>> I would prefer a style like
>>
>> myfunc := @function(x, y: Integer): Integer Result := x + y;
>
> And how would you create more complex functions? In Pascal code blocks
> are started with "begin" and ended with "end". I don't see a reason why
> anonymous methods should differ here.
>
> Also the example given by Embarcadero is a bit boring. The interesting
> thing about anonymous methods (and nested functions types in FPC) is
> that they can access variables of the surrounding function (at least I
> hope that I've understand it correctly that nested function types can do
> that).


The main difference between anonymous methods and nested functions is
that one can return a reference to an anonymous method from a function,
the anonymous method can access local variables from that function and
even after exiting the function, the variables are still valid. This
means that local variables accessed in a anonymous method end up on the
heap.

However, I fail to see reasonable use cases for anonymous methods
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Delphi's anonymous functions in Free Pascal

Andrew Pennebaker
Practical uses for referencable anonymous functions:

(map f collection)

This is the prototypical way to run a function over each element in a collection, returning the results.

Example:

(map (lambda (x) (+ x 1)) '(1 2 3))

-> (2 3 4)

(sort compare collection)

When dealing with complex data types, the user may want to implement a custom compare function.

(sort (lambda (x y) (- y:employee-id x:employeeid)) (list emp1 emp2 emp3))

-> (emp3 emp1 emp2)

(zip f collection1 collection2)

Similar to map, zip runs a 2-input function over the elements of the collections, returning the results.

(zip (lamba (x y) (+ x y)) '(1 2 3) '(4 5 6))

-> (5 7 9)

At first glance, each of these examples may seem pointless. Can't we implement the same behavior without referencing anonymous functions? Yes, we can, but only for a specific function. If you want your database library to allow users to customize sorting, you'll need referencable anonymous functions.

If you've used a functional language, you know how powerful these little functions are, and you'll miss them and want to implement them in languages that don't have them.

Cheers,

Andrew Pennebaker

On Wed, Oct 19, 2011 at 2:04 PM, Florian Klämpfl <[hidden email]> wrote:
Am 19.10.2011 10:16, schrieb Sven Barth:
> Am 19.10.2011 09:31, schrieb Michael Fuchs:
>> I would prefer a style like
>>
>> myfunc := @function(x, y: Integer): Integer Result := x + y;
>
> And how would you create more complex functions? In Pascal code blocks
> are started with "begin" and ended with "end". I don't see a reason why
> anonymous methods should differ here.
>
> Also the example given by Embarcadero is a bit boring. The interesting
> thing about anonymous methods (and nested functions types in FPC) is
> that they can access variables of the surrounding function (at least I
> hope that I've understand it correctly that nested function types can do
> that).


The main difference between anonymous methods and nested functions is
that one can return a reference to an anonymous method from a function,
the anonymous method can access local variables from that function and
even after exiting the function, the variables are still valid. This
means that local variables accessed in a anonymous method end up on the
heap.

However, I fail to see reasonable use cases for anonymous methods
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Delphi's anonymous functions in Free Pascal

Florian Klämpfl
Am 19.10.2011 20:23, schrieb Andrew Pennebaker:
> Practical uses for referencable anonymous functions:

For such applications one uses procedure variables in pascal.

>
> (map f collection)
>
> This is the prototypical way to run a function over each element in a
> collection, returning the results.
>
> Example:
>
> (map (lambda (x) (+ x 1)) '(1 2 3))
>
> -> (2 3 4)
>
> (sort compare collection)
>
> When dealing with complex data types, the user may want to implement a
> custom compare function.
>
> (sort (lambda (x y) (- y:employee-id x:employeeid)) (list emp1 emp2 emp3))
>
> -> (emp3 emp1 emp2)
>
> (zip f collection1 collection2)
>
> Similar to map, zip runs a 2-input function over the elements of the
> collections, returning the results.
>
> (zip (lamba (x y) (+ x y)) '(1 2 3) '(4 5 6))
>
> -> (5 7 9)
>
> At first glance, each of these examples may seem pointless. Can't we
> implement the same behavior without referencing anonymous functions?
> Yes, we can, but only for a specific function. If you want your database
> library to allow users to customize sorting, you'll need referencable
> anonymous functions.

I still don't see why this cannot be done by procedure variables: one
can easily pass a procedure reference to a compare function to any sort
library call. The example is far from explaining why it is needed to be
able to return a reference to an anonymous method to the outside of the
enclosing function.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
1234 ... 7