Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2011-10

Delphi's anonymous functions in Free Pascal

125 messages · 30 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

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
www.yellosoft.us

Reply by email

Sven Barth
to Andrew Pennebaker
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?

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

Reply by email

Lukasz Sokol
to Andrew Pennebaker: Does Free Pascal have anonymous functions that you can pass around, e.g. to a…
Andrew Pennebaker wrote 9 lines
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.

Reply by email

Andrew Pennebaker
to Lukasz Sokol: Yes: //you can declare a type : TMyFunction: function(AMyParam : TType): TOtherType; //…

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?

GitHub <https://github.com/mcandre/paycheck>

Cheers,

Andrew Pennebaker
www.yellosoft.us

Lukasz Sokol wrote 104 lines
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 - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

Roland Schäfer
to Andrew Pennebaker
Andrew Pennebaker wrote 7 lines
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

Show quoted text 102 lines
On Tue, Oct 18, 2011 at 4:57 AM, Lukasz Sokol 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. >

Reply by email

Alberto Narduzzi
to Andrew Pennebaker: Sokol, I'm writing a function GenArray(generator) that returns a random array populated…

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.

Reply by email

Sven Barth
to Roland Schäfer: Sven pointed out yesterday that you cannot achieve in FPC what you want to achieve. (I…
Roland Schäfer wrote 5 lines
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

Reply by email

Andrew Pennebaker
to Roland Schäfer: Sven pointed out yesterday that you cannot achieve in FPC what you want to achieve. (I…

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

Show quoted text 159 lines
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 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 - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

Roland Schäfer
to Andrew Pennebaker
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

Reply by email

Andrew Pennebaker
to Roland Schäfer

The procedural types<http://www.freepascal.org/docs-html/ref/refse17.html#x45-520003.6>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 <https://github.com/mcandre/qc>, issue a pull request.

Cheers,

Andrew Pennebaker
www.yellosoft.us

2011/10/18 Roland Schäfer

Show quoted text 44 lines
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

Reply by email

Michael Fuchs
to Sven Barth: For anonymous functions you can take a look at Embarcadero's Delphi help here:…
Sven Barth wrote
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

Reply by email

Sven Barth
to Michael Fuchs
Michael Fuchs wrote
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

Reply by email

Lukasz Sokol
to Andrew Pennebaker: Sokol, I'm writing a function GenArray(generator) that returns a random array populated…

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

Reply by email

Michael Fuchs
to Sven Barth: And how would you create more complex functions? In Pascal code blocks are started with…
Sven Barth wrote 7 lines
> 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

Reply by email

Alexander Shishkin
to Sven Barth: And how would you create more complex functions? In Pascal code blocks are started with…

19.10.2011 12:16, Sven Barth пишет:

Show quoted text 46 lines
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 - 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;"

Reply by email

Florian Klämpfl
to Sven Barth: And how would you create more complex functions? In Pascal code blocks are started with…
Sven Barth wrote 14 lines
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

Reply by email

Andrew Pennebaker
to Florian Klämpfl

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
www.yellosoft.us

Florian Klämpfl wrote 29 lines
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 - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

Florian Klämpfl
to Andrew Pennebaker
Andrew Pennebaker wrote
Practical uses for referencable anonymous functions:

For such applications one uses procedure variables in pascal.

Show quoted text 35 lines
(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.

Reply by email

Michael Fuchs
to Florian Klämpfl
Florian Klämpfl wrote
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.

It is maybe easier to write a anonymous function inline than declaring a function and passing it with a reference to this function.

Sometimes I miss them in FPC, but I am also not sure if this feature destroys the beauty of Pascal.

Not easy.

Michael

Reply by email

Andrew Pennebaker
to Florian Klämpfl: For such applications one uses procedure variables in pascal. I still don't see why this…
From what I gather, procedure variables can indeed be referenced and passed

around, etc.

However, procedures do not return anything, so it's hard to chain them. In functional languages, it's handy to do several nested map(map(map f ... calls.

Cheers,

Andrew Pennebaker
www.yellosoft.us

Florian Klämpfl wrote 51 lines
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 - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

Sven Barth
to Andrew Pennebaker
Andrew Pennebaker wrote 6 lines
>From what I gather, procedure variables can indeed be referenced and passed around, etc. However, procedures do not return anything, so it's hard to chain them. In functional languages, it's handy to do several nested map(map(map f ... calls.

Pascal isn't a functional language. You'll need to find other ways to do this in Pascal as other Pascal users have found ways to implement their code. You could try object oriented programming for example (though I don't know a specific solution for "map").

Regards,
Sven

Reply by email

Gregory M. Turner
to Florian Klämpfl: For such applications one uses procedure variables in pascal. I still don't see why this…

----- Original Message -----

Show quoted text 9 lines
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 (lambda (x) (+ x 1)) '(1 2 3)) > > -> (2 3 4)

[snip!]

Show quoted text 8 lines
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.

[not_sure_if_serious.png]

Interesting discussion -- at least for me, I didn't know Delphi had this feature.

In case anyone really doesn't see the point, consider that this thing:

http://www.youtube.com/watch?v=cYw2ewoO6c4

has all the capabilities of Object Pascal (with less flowery syntactic sugar to mess up the purity of the system).

:P

Greg Turner P.S., hello, list!

Reply by email

Florian Klämpfl
to Gregory M. Turner
Gregory M. Turner wrote 8 lines
Interesting discussion -- at least for me, I didn't know Delphi had this feature. In case anyone really doesn't see the point, consider that this thing: http://www.youtube.com/watch?v=cYw2ewoO6c4 has all the capabilities of Object Pascal (with less flowery syntactic sugar to mess up the purity of the system).

If anybody does not see why increasing complexity without a good reason should be avoided, I recommend:

http://www.youtube.com/watch?v=kYUrqdUyEpI

Reply by email

Juha Manninen
to Florian Klämpfl: If anybody does not see why increasing complexity without a good reason should be…

2011/10/20 Florian Klämpfl

Show quoted text 5 lines
If anybody does not see why increasing complexity without a good reason should be avoided, I recommend: http://www.youtube.com/watch?v=kYUrqdUyEpI

:-)

There is lots of confusion about anonymous functions. The name is misleading, they are called closures in other languages. There was a similar discussion earlier, see :
http://www.hu.freepascal.org/lists/fpc-pascal/2010-January/023755.html

The origin is from functional languages but it is fine to borrow it to OP, the same way classes and object features were borrowed earlier from other languages. Besides I think the closure addition is almost as important.

They have some very important uses, like making multithreading easier. I copy text from Delphi help page again here because it looks so cool:

--------------------------------------------------------- Using Code for a Parameter

Anonymous methods make it easier to write functions and structures parameterized
by code, not just values.

Multithreading is a good application for anonymous methods. if you want to execute
some code in parallel,
you might have a parallel-for function that looks like this:

type
TProcOfInteger = reference to procedure(x: Integer);
procedure ParallelFor(start, finish: Integer; proc: TProcOfInteger);

The ParallelFor procedure iterates a procedure over different threads.

Assuming this procedure is implemented correctly and efficiently using threads
or a thread pool, it could then be easily used to take advantage of multiple processors:

procedure CalculateExpensiveThings;
var
results: array of Integer;
begin
SetLength(results, 100);
ParallelFor(Low(results), High(results),
procedure(i: Integer) // \
begin // \ code block
results[i] := ExpensiveCalculation(i); // / used as parameter
end // /
);
// use results
end;

Contrast this to how it would need to be done without anonymous methods: probably a "task" class with a virtual abstract method, with a concrete descendant for ExpensiveCalculation, and then adding all the tasks to a queue--not nearly as natural or integrated.

Here, the "parallel-for" algorithm is the abstraction that is being parameterized by code. In the past, a common way to implement this pattern is
with a virtual base class with one or more abstract methods; consider the TThread class and its abstract Execute method. However, anonymous methods make
this pattern--parameterizing of algorithms and data structures using code--far
easier.

Regards,
Juha Manninen

Reply by email

Florian Klämpfl
to Juha Manninen: 2011/10/20 Florian Klämpfl :-) There is lots of confusion about anonymous functions. The…
Juha Manninen wrote
They have some very important uses, like making multithreading easier. I copy text from Delphi help page again here because it looks so cool:

The same can be done with fpc (nested if needed) procedure variables and it will be more readable (imo)? The example still does not take advantage of properties of anonymous methods/closurs which cause complexity like being ref. counted, putting locals on the heap etc.

Reply by email

waldo kitty
to Florian Klämpfl: If anybody does not see why increasing complexity without a good reason should be…
Florian Klämpfl wrote 15 lines
Am 20.10.2011 21:09, schrieb Gregory M. Turner: > > Interesting discussion -- at least for me, I didn't know Delphi had this feature. > > In case anyone really doesn't see the point, consider that this thing: > > http://www.youtube.com/watch?v=cYw2ewoO6c4 > > has all the capabilities of Object Pascal (with less flowery syntactic sugar to mess up the purity of the system). If anybody does not see why increasing complexity without a good reason should be avoided, I recommend: http://www.youtube.com/watch?v=kYUrqdUyEpI

+1000000000000~

;)

Reply by email

Andrew Pennebaker
to Florian Klämpfl: If anybody does not see why increasing complexity without a good reason should be…

If anybody does not see why increasing complexity without a good reason should be avoided, I recommend:

http://www.youtube.com/watch?v=kYUrqdUyEpI

Lisp used for nuclear fail-safe
systems<http://books.google.com/books?id=5fbyVju-LJ8C&pg=PA75&lpg=PA75&dq=lisp+nuclear+reactor&source=bl&ots=EMUJzJKT0D&sig=LCb3KDYjiSpzh0-76R1LdJm8rJc&hl=en&ei=886gTu-sAunm0QHtmrz6BA&sa=X&oi=book_result&ct=result&resnum=3&sqi=2&ved=0CC0Q6AEwAg#v=onepage&q=lisp%20nuclear%20reactor&f=false>. I doubt languages without *map* are up to the job.

Cheers,

Andrew Pennebaker
www.yellosoft.us

Florian Klämpfl wrote 21 lines
Am 20.10.2011 21:09, schrieb Gregory M. Turner: > > Interesting discussion -- at least for me, I didn't know Delphi had this feature. > > In case anyone really doesn't see the point, consider that this thing: > > http://www.youtube.com/watch?v=cYw2ewoO6c4 > > has all the capabilities of Object Pascal (with less flowery syntactic sugar to mess up the purity of the system). If anybody does not see why increasing complexity without a good reason should be avoided, I recommend: http://www.youtube.com/watch?v=kYUrqdUyEpI _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

Jürgen Hestermann
to Florian Klämpfl: If anybody does not see why increasing complexity without a good reason should be…
If anybody does not see why increasing complexity without a good reason should be avoided, I recommend:

I agree wholeheartly. In the past Pascal was a simple still powerfull language but meanwhile it has become a catchment tank for all features of all other languages. This defeats the original intention of Nicholas Wirth and the reason for what I love(d) the language. It seems everybody tries to mimic Pascal into whatever he is used to do in other languages. So we should no longer call this (Object) Pascal but "Chimera".

Reply by email

Juha Manninen
to Jürgen Hestermann: I agree wholeheartly. In the past Pascal was a simple still powerfull language but…

2011/10/21 Jürgen Hestermann

Show quoted text 12 lines
Florian Klämpfl schrieb: > If anybody does not see why increasing complexity without a good reason > should be avoided, I recommend: I agree wholeheartly. In the past Pascal was a simple still powerfull language but meanwhile it has become a catchment tank for all features of all other languages. This defeats the original intention of Nicholas Wirth and the reason for what I love(d) the language. It seems everybody tries to mimic Pascal into whatever he is used to do in other languages. So we should no longer call this (Object) Pascal but "Chimera".

Please look at some old Pascal code from 80's. Lots of shortstring manipulation with pointers. Very much comparable to C, and as prone to errors as C.
It is good to realize that Pascal would have died already without the class/object additions made by Borland.
The challenge is to add only the RIGHT features. In school I must study again C++ and they clearly did it wrong. Uhhh!
IMO the OP additions have been good so far. For example generics containers eliminate ugly type-casts. It is an improvement, clearly.

Closures seem like a powerful thing which can improve code. Now Florian mentioned that procedure variables could do the same thing. I clearly don't understand the topic enough, I must learn more.

It is funny how fashion trends also affect the evolution of programming languages.
When object oriented programming became a trend, everything had to be an object.
Java libs are a good example. Some classes (nouns) have only one method (verb) called "Execute".
Translated to human languages, it is like "man's walking executor executes" instead of "man walks".

Now the functional languages turn fashionable, maybe as a counter-effect to OO.
Some people said that programming became funny again when using a functional language (Haskel was it?).
I also want to learn and understand how to say things with only functions (verbs).

All this turbulence proves how young is the evolution of programming languages. Human languages have a much longer evolution. You can see they have a versatile syntax. They have lots of redundancy and synonyms to ensure "error free message delivery".
The syntax (grammer) is not always simple but it is expressive.

Juha

Reply by email

Graeme Geldenhuys
to Florian Klämpfl: The same can be done with fpc (nested if needed) procedure variables and it will be more…
Florian Klämpfl wrote
The same can be done with fpc (nested if needed) procedure variables and it will be more readable (imo)? The example still does not take

This seldom happens, but here I fully agree with Florian. ;-) Every example of anonymous methods I have seen so far, can easily be done with OP's procedure variables too. Maybe anonymous methods were introduced in other languages because they didn't have something like OP's procedure variables. I guess Object Pascal was yet again ahead of everybody else. :)

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/

Reply by email

leledumbo
to Graeme Geldenhuys
Maybe anonymous methods were introduced

in other languages because they didn't have something like OP's procedure variables

IMO, it's because they're lazy to declare things before they use it. Often, an anonymous function which first used just once eventually used more than once. When that happens, users of languages with anonymous function would refactor the function by removing it from the anonymous context into a standalone named function, and re-pass it. Where as for Pascal style users, that's not needed because the function is already named and standalone.

View this message in context: http://free-pascal-general.1045716.n5.nabble.com/Delphi-s-anonymous-functions-in-Free-Pascal-tp4911527p4925137.html Sent from the Free Pascal - General mailing list .

Reply by email

Alexander Shishkin
to Andrew Pennebaker: Does Free Pascal have anonymous functions that you can pass around, e.g. to a…

18.10.2011 0:53, Andrew Pennebaker пишет:

Does Free Pascal have anonymous functions that you can pass around, e.g. to a sort(compare : function, arr : array) function?

anonymous functions = closures = lambdas are part of functional paradigm. object pascal itself is not functional language. But there is modern trend to design multiparadigm languages (usually OO
+ functional + imperative).
Delphi followed this trend. So the question is: should freepascal follow this trend too?

Reply by email

Jürgen Hestermann
to Juha Manninen: 2011/10/21 Jürgen Hestermann Please look at some old Pascal code from 80's. Lots of…
Please look at some old Pascal code from 80's. Lots of shortstring

manipulation with pointers. Very much comparable to C, and as prone to errors as C.

Yes, new string types were needed. But why not doing it right in one step? Instead we now have lots of different string representations which all have their own peculiarities which everybody has to learn. To me it seems that all these changes were hasty hacks and are now cast in stone to live forever in the (object) Pascal language to annoy following generations of Pascal programmers. If things are only added and nothing is ever removed than the language becomes bloated.

It is good to realize that Pascal would have died already without the

class/object additions made by Borland.

I doubt that. I don't see any merrit in objects. You can do all the same with units that declare functions and data types. You can also build an IDE that helps you finding functions/procedure that act on special data types. There is no innovation in object oriented programming. Just the opposite: If I create a button "object" on my form that does something I would expect it to act when I click on it. But that does not happen because in the background there is still the procedural processor that goes through a sequential list of commands. Real objects would be able to act independently and can interact. But this would require a core for each object which I fail to see in the near future.

I am just thinking how a child or teenager who learns programming would think about it. He may not unterstand why you need to add "Application.ProcessMessages;" calls into loops to keep the button responsive. This is hiding away important information. Instead of OOP it should have been named DAF (Data Attached Functions) or so.

Also, why can operators be overloaded? Operators are fundamental parts of a programming language and to me it makes no sense to irk programmers by changing its meaning.

Also, why suddenly extend the meaning of := ? It should be a simple byte movement, nothing else (only exception should be number type convertion). Doing arbitrary complex things when using it does not make a clearer code. And for what reason? Just to save writing a function call? That cannot be the direction to go. Maybe we see BEGIN and END and the semicolon doing things too. How can one read such code? And how much does a new user have to learn to use the Pascal language?

It could also be that it's only a matter of documentation and learning. As many others I don't have very much time to read about and test new features. And I also don't have to. I never failed to do what I wanted and it was very speedy (unless I had to use some obscure "library" which was slow) and the code is still clear and readable.

The challenge is to add only the RIGHT features.

That's true. But now the mark is overshot already.

IMO the OP additions have been good so far. For example generics

containers eliminate ugly type-casts. It is an improvement, clearly.

I can't say anything about this because I don't know the concept.

Closures seem like a powerful thing which can improve code.

Same as for closures, I don't know them.

Now Florian mentioned that procedure variables could do the same

thing. I clearly don't understand the topic enough, I must learn more.

I see that many of these new concepts are added because people come from other languages and want to do things the same way. But often it can already be done with the existing language and even faster. I was able to code everything I wanted in the past 25 years without objects and without closures and all this other stuff. But if I now try to understand foreign code I am totally lost because here these things are used.

Reply by email

Marco van de Voort
to Jürgen Hestermann

The link below describes two uses for anonymous methods.

http://stackoverflow.com/questions/7818759/delphi-anonymus-methods-pro-and-cons-good-practices-when-using-closuresanony/7821882#comment9576663_7821882

I don't entirely subscribe to the (1) one, it seems to be mostly a shorthand argument.

But (2) is somewhat logical and interesting. an. funcs allow to wrap a call to a procedure together with its arguments inside a anonymous function (closure-like) and queue that in a different thread and have it executed there by RTL code.

I think that (2) is the main reason for anonymous functions, and people shouldn't assume that the use of an. funcs is the same as in functional languages. (IOW for expressions)

Reply by email

Gregory M. Turner
to Alexander Shishkin: 18.10.2011 0:53, Andrew Pennebaker пишет: anonymous functions = closures = lambdas…

----- Original Message -----

Show quoted text 14 lines
18.10.2011 0:53, Andrew Pennebaker пишет: > Does Free Pascal have anonymous functions that you can pass around, > e.g. > to a sort(compare : function, arr : array) function? > anonymous functions = closures = lambdas are part of functional paradigm. object pascal itself is not functional language. But there is modern trend to design multiparadigm languages (usually OO + functional + imperative). Delphi followed this trend. So the question is: should freepascal follow this trend too?

Taking these terms in the broadest sense possible, wouldn't we say that OOP is mostly a functional development paradigm?

Not a rhetorical question, I seriously am not sure.

OP's somewhat idiosyncratic requirement to put all the OOP metadata in a separate interface section of your code kind of underlines what I'm talking about. It seems to me that in OOP, whatever we might happen to do procedurally, there's a strong declarative odor to everything happening at the class/interface level.

-gmt

Reply by email

Juha Manninen
to Gregory M. Turner

2011/10/22 Gregory M. Turner

Show quoted text 12 lines
Taking these terms in the broadest sense possible, wouldn't we say that OOP is mostly a functional development paradigm? Not a rhetorical question, I seriously am not sure. OP's somewhat idiosyncratic requirement to put all the OOP metadata in a separate interface section of your code kind of underlines what I'm talking about. It seems to me that in OOP, whatever we might happen to do procedurally, there's a strong declarative odor to everything happening at the class/interface level.

Now you are mixing the well-established terms.
Functional programming paradigm is based on lambda calculus. There are no loop constructs or even variables in normal sense. There are only functions which return a value without side-effects.

In Object Pascal you must define types in interface, but it doesn't change the object oriented paradigm anyhow.
In Java or C# you don't have interface definitions but they still have the same paradigm.

Wikipedia has amazingly much info. See:

http://en.wikipedia.org/wiki/Functional_programming

On the right edge there is a list "Programming Paradigms".

Regards,
Juha

Reply by email

waldo kitty
to Jürgen Hestermann: I agree wholeheartly. In the past Pascal was a simple still powerfull language but…
Jürgen Hestermann wrote 10 lines
Florian Klämpfl schrieb: > If anybody does not see why increasing complexity without a good reason > should be avoided, I recommend: I agree wholeheartly. In the past Pascal was a simple still powerfull language but meanwhile it has become a catchment tank for all features of all other languages. This defeats the original intention of Nicholas Wirth and the reason for what I love(d) the language. It seems everybody tries to mimic Pascal into whatever he is used to do in other languages. So we should no longer call this (Object) Pascal but "Chimera".

+1 (based on some of the recent stuff being posted :) )

Reply by email

Unknown author
to Graeme Geldenhuys: This seldom happens, but here I fully agree with Florian. ;-) Every example of anonymous…

+1
----- Mail Original -----
De: "Graeme Geldenhuys"
À: "FPC-Pascal users discussions"
Envoyé: Vendredi 21 Octobre 2011 10h03:27 GMT +01:00 Amsterdam / Berlin / Berne / Rome / Stockholm / Vienne Objet: Re: [fpc-pascal] Re: Delphi's anonymous functions in Free Pascal

Florian Klämpfl wrote
The same can be done with fpc (nested if needed) procedure variables and it will be more readable (imo)? The example still does not take

This seldom happens, but here I fully agree with Florian. ;-) Every example of anonymous methods I have seen so far, can easily be done with OP's procedure variables too. Maybe anonymous methods were introduced in other languages because they didn't have something like OP's procedure variables. I guess Object Pascal was yet again ahead of everybody else. :)

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/

Reply by email

Marco van de Voort
to Unknown author

In our previous episode, said:

Show quoted text 8 lines
> it will be more readable (imo)? The example still does not take This seldom happens, but here I fully agree with Florian. ;-) Every example of anonymous methods I have seen so far, can easily be done with OP's procedure variables too. Maybe anonymous methods were introduced in other languages because they didn't have something like OP's procedure variables. I guess Object Pascal was yet again ahead of everybody else. :)

I hinted on it in earlier procedures, but here a typical anonymous method usecase.

You are in a thread and want to call a method or procedure in a different thread. (to the mainthread or a different event driven thread)

BUT, the said function takes parameters. WDYD?

Classically, you create some record, add all paramters to it, dump it in some queue (or argument to a windows message if you play it dirty), write a procedure in the destination thread that gets the record from the queue, and calls the function with the parameters.

One can avoid doing the queue for every case by using a bit of OOP, but still you need to inherit and implement that object for every signature of a method that you want to call cross-thread this way. Loading parameters into it in the source thread, and calling the destination procedure with parameters in the execute method for the destination thread.

Using the anonymous function however, you put the call within the anonymous function block. This blocks captures all necessary state, and boom it is away.

Visually:

Problem:

call

targetobject.destinationfunction(a:integer;b:someobject;c:string);

in a different thread.

Classic solution:

type  // for every signature:
   TMyobject = class(TpseudoClosure)
                a:integer;
                b:someobject;
                c:string;
                tgob: TTargetObject;
                procedure execute; override;
              end;
procedure TMyObject.Execute;
begin
  tgob.destinationfunction(a,b,c);
end;
// once:
var
  thrqueue :TSomeGenericThreadsafeQUeue<TPseudoClosure>;
procedure tmythread.syncfunc;
var x:TPseudoClosure;
begin
  x:=getqueuecurrentthread().popitem; // get closure object from queue
  x.execute;
  x.free;
end;
// calling from source thread;

var x : TPseudoclosure

x:=TMyObject.Create;
x.a:=a;
x.b:=b;
x.c:=c;
tboj:=targetobject;
queuefortargetthread.pushitem(x);
queuefortargetthread.queue(syncfunc); // call item async in other thread.
                                      // tthread.queue not yet in FPC

I have many such constructs in my current framework. Of course you start to double use simple objects, and not all cases use 3 parameters. It is just for the idea.

Note that tabstractclosure, the generic queue etc must also be defined, but that is so general it could be in the RTL, and not a burden

---------------------------------
vs
-~-------------------------------

Equivalent solution with anon functions:

targethread.queue(
   procedure(targetobject:ttargetobject;a:integer;b:someobject;c:string)
              begin
                targetobject.destinationprocedure(a,b,c);
              end;

Note how common this looks compared to the original.

Btw: I don't know this function this well. I only described it how I saw it in several D2010 blogs. I still support D2009, and the framework design was even older, so I don't actively use it.

Reply by email

Unknown author
to Marco van de Voort
Marco van de Voort wrote 12 lines
In our previous episode, said: >> it will be more readable (imo)? The example still does not take > > This seldom happens, but here I fully agree with Florian. ;-) Every > example of anonymous methods I have seen so far, can easily be done with > OP's procedure variables too. Maybe anonymous methods were introduced > in other languages because they didn't have something like OP's > procedure variables. I guess Object Pascal was yet again ahead of > everybody else. :) I hinted on it in earlier procedures, but here a typical anonymous method usecase.

[snip]

Show quoted text 11 lines
-~------------------------------- Equivalent solution with anon functions: targethread.queue( procedure(targetobject:ttargetobject;a:integer;b:someobject;c:string) begin targetobject.destinationprocedure(a,b,c); end; Note how common this looks compared to the original.

One point is that you could do the above with a local (and named) procedure as well, and still have all the context. At the very least you would not be raping pascal's readability by putting a complete procedure declaration inside a code block.

I don't know about you, but I have serious trouble reading the above monstrosity. It looks like you forgot the closing ) for the queue call.

Michael.

Reply by email

Marco van de Voort
to Unknown author

In our previous episode, said:

Show quoted text 17 lines
> > targethread.queue( > procedure(targetobject:ttargetobject;a:integer;b:someobject;c:string) > begin > targetobject.destinationprocedure(a,b,c); > end; > > Note how common this looks compared to the original. One point is that you could do the above with a local (and named) procedure as well, and still have all the context. At the very least you would not be raping pascal's readability by putting a complete procedure declaration inside a code block. I don't know about you, but I have serious trouble reading the above monstrosity. It looks like you forgot the closing ) for the queue call.

One can debate the syntax. I won't, since even while I have similar reservations, that will lead to the usual Delphi sucks debate, possible implementation of an-orphaned-at-birth FPC specific syntax, and in the end the Delphi syntax always prevails, leading to a lot of wasted time in discussion and implementation of own inventions.

That is such a common pattern on these lists, I'm thinking about an acronym for it to save time :-) So sufficient to say, I think own syntax inventions are worse than the problem in the first place, and sooner or later we have to live with it.

However there was also a questioning of the use(functionality) of anonymous functions, I hope that I have now at least explained a typical use case, so we can put that to rest.

Reply by email

Unknown author
to Marco van de Voort
Marco van de Voort wrote 33 lines
In our previous episode, said: >> >> targethread.queue( >> procedure(targetobject:ttargetobject;a:integer;b:someobject;c:string) >> begin >> targetobject.destinationprocedure(a,b,c); >> end; >> >> Note how common this looks compared to the original. > > One point is that you could do the above with a local (and named) > procedure as well, and still have all the context. > At the very least you would not be raping pascal's readability by putting a > complete procedure declaration inside a code block. > > I don't know about you, but I have serious trouble reading the above monstrosity. > It looks like you forgot the closing ) for the queue call. One can debate the syntax. I won't, since even while I have similar reservations, that will lead to the usual Delphi sucks debate, possible implementation of an-orphaned-at-birth FPC specific syntax, and in the end the Delphi syntax always prevails, leading to a lot of wasted time in discussion and implementation of own inventions. That is such a common pattern on these lists, I'm thinking about an acronym for it to save time :-) So sufficient to say, I think own syntax inventions are worse than the problem in the first place, and sooner or later we have to live with it. However there was also a questioning of the use(functionality) of anonymous functions, I hope that I have now at least explained a typical use case, so we can put that to rest.

Please note that I didn't question their use, just the syntax :)

Michael.

Reply by email

Lukasz Sokol
to Marco van de Voort: In our previous episode, said: One can debate the syntax. I won't, since even while I…
Marco van de Voort wrote 11 lines
One can debate the syntax. I won't, since even while I have similar reservations, that will lead to the usual Delphi sucks debate, possible implementation of an-orphaned-at-birth FPC specific syntax, and in the end the Delphi syntax always prevails, leading to a lot of wasted time in discussion and implementation of own inventions. That is such a common pattern on these lists, I'm thinking about an acronym for it to save time :-) So sufficient to say, I think own syntax inventions are worse than the problem in the first place, and sooner or later we have to live with it.

[OT]
It's the Let's Screw FPC Guys Life [LSFGL] warrior call of the Borland/CodeGear/Embracadero employees ;)

L.

Reply by email

Lukasz Sokol
to Lukasz Sokol
Lukasz Sokol wrote 20 lines
On 25/10/2011 12:52, Marco van de Voort wrote: > One can debate the syntax. I won't, since even while I have > similar reservations, that will lead to the usual Delphi sucks > debate, possible implementation of an-orphaned-at-birth FPC > specific syntax, and in the end the Delphi syntax always prevails, > leading to a lot of wasted time in discussion and implementation of > own inventions. > > That is such a common pattern on these lists, I'm thinking about an > acronym for it to save time :-) So sufficient to say, I think own > syntax inventions are worse than the problem in the first place, > and sooner or later we have to live with it. > [OT] It's the Let's Screw FPC Guys Life [LSFGL] warrior call of the Borland/CodeGear/Embracadero employees ;) L.

or Change Lazarus And QUit Emancipating language-Rules (CLAQUER).

:J
L.

Reply by email

Bernd
to Unknown author: [snip] One point is that you could do the above with a local (and named) procedure as…

2011/10/25 :

Show quoted text 12 lines
> targethread.queue( >  procedure(targetobject:ttargetobject;a:integer;b:someobject;c:string) >             begin >               targetobject.destinationprocedure(a,b,c); >             end; > > Note how common this looks compared to the original. One point is that you could do the above with a local (and named) procedure as well, and still have all the context. At the very least you would not be raping pascal's readability by putting a complete procedure declaration inside a code block.

How would you preserve the context without finding some place somewhere (on the heap) to store the current values of a, b, and c?

The natural alternative to a closure if you don't have them in an OO language is instead of passing a closure you pass an object (this pattern is called Functor). The object contains the function along with some state. Of course in a static language this involves a lot of boiler plate to define the needed classes with their methods (one class definition for every different closure) but once you have done this you can use it like the closure in the above example and its usage is totally readable:

targetthread.queue(TMyFunctor.Create(targetobject, a, b, c));

Reply by email

Bernd
to Marco van de Voort: In our previous episode, said: I hinted on it in earlier procedures, but here a typical…

2011/10/25 Marco van de Voort :

Show quoted text 7 lines
Equivalent solution with anon functions: targethread.queue(   procedure(targetobject:ttargetobject;a:integer;b:someobject;c:string)              begin                targetobject.destinationprocedure(a,b,c);              end;

shouldn't this be

targethread.queue(
      procedure
             begin
               targetobject.destinationprocedure(a,b,c);
             end;

without any parameters since all these variables are captured from the current scope into the closure? The other thread should not need to know anything about them to call it.

Reply by email

Marco van de Voort
to Bernd

In our previous episode, Bernd said:

Show quoted text 19 lines
> Equivalent solution with anon functions: > > targethread.queue( > ? procedure(targetobject:ttargetobject;a:integer;b:someobject;c:string) > ? ? ? ? ? ? ?begin > ? ? ? ? ? ? ? ?targetobject.destinationprocedure(a,b,c); > ? ? ? ? ? ? ?end; shouldn't this be targethread.queue( procedure begin targetobject.destinationprocedure(a,b,c); end; without any parameters since all these variables are captured from the current scope into the closure? The other thread should not need to know anything about them to call it.

Afaik you are right. Delphi also allowed the other form, but I thought the syntax would force immediately evaluation of the parameters (and thus only the parameters be stored in case any of a ,b or c are expressions, not all parts of the expressions).

But indeed then the other side also has to call it with parameters, and in this example that defeats the purpose.

Reply by email

Alexander Shishkin
to Bernd: 2011/10/25 : How would you preserve the context without finding some place somewhere (on…

05.11.2011 22:42, Bernd пишет:

Show quoted text 34 lines
2011/10/25: >> targethread.queue( >> procedure(targetobject:ttargetobject;a:integer;b:someobject;c:string) >> begin >> targetobject.destinationprocedure(a,b,c); >> end; >> >> Note how common this looks compared to the original. > > One point is that you could do the above with a local (and named) procedure > as well, and still have all the context. At the very least you would not be > raping pascal's readability by putting a > complete procedure declaration inside a code block. How would you preserve the context without finding some place somewhere (on the heap) to store the current values of a, b, and c? The natural alternative to a closure if you don't have them in an OO language is instead of passing a closure you pass an object (this pattern is called Functor). The object contains the function along with some state. Of course in a static language this involves a lot of boiler plate to define the needed classes with their methods (one class definition for every different closure) but once you have done this you can use it like the closure in the above example and its usage is totally readable: targetthread.queue(TMyFunctor.Create(targetobject, a, b, c)); _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

But modern trend is to add closures into OO languages, because code become more laconic.

Reply by email

Michael Van Canneyt
to Bernd: 2011/10/25 : How would you preserve the context without finding some place somewhere (on…
Bernd wrote 18 lines
2011/10/25 : >> targethread.queue( >>  procedure(targetobject:ttargetobject;a:integer;b:someobject;c:string) >>             begin >>               targetobject.destinationprocedure(a,b,c); >>             end; >> >> Note how common this looks compared to the original. > > One point is that you could do the above with a local (and named) procedure > as well, and still have all the context. At the very least you would not be > raping pascal's readability by putting a > complete procedure declaration inside a code block. How would you preserve the context without finding some place somewhere (on the heap) to store the current values of a, b, and c?
Procedure SomeOuter;
Var
   d,e,f : SomeType;
   Procedure SomeInner(targetobject:ttargetobject;a:integer;b:someobject;c:string)
  begin
      targetobject.destinationprocedure(a,b,c);
  end;
begin
   Targethread.queue(@SomeInner(aobject,d,e,f));
end;

No difference with 'closure', except more readable.

Michael.

Reply by email

Alexander Shishkin
to Michael Van Canneyt

06.11.2011 1:46, Michael Van Canneyt пишет:

Show quoted text 48 lines
On Sat, 5 Nov 2011, Bernd wrote: > 2011/10/25 : > >>> targethread.queue( >>> procedure(targetobject:ttargetobject;a:integer;b:someobject;c:string) >>> begin >>> targetobject.destinationprocedure(a,b,c); >>> end; >>> >>> Note how common this looks compared to the original. >> >> One point is that you could do the above with a local (and named) >> procedure >> as well, and still have all the context. At the very least you would >> not be >> raping pascal's readability by putting a >> complete procedure declaration inside a code block. > > How would you preserve the context without finding some place > somewhere (on the heap) to store the current values of a, b, and c? > Procedure SomeOuter; Var d,e,f : SomeType; Procedure SomeInner(targetobject:ttargetobject;a:integer;b:someobject;c:string) begin targetobject.destinationprocedure(a,b,c); end; begin Targethread.queue(@SomeInner(aobject,d,e,f)); end; No difference with 'closure', except more readable. Michael. _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Closures can be returned as a function result but nested procedure not (more strictly, this can be complied but will not work because of lifetime of nested procedure).

Reply by email

Bernd
to Michael Van Canneyt: Procedure SomeOuter; Var d,e,f : SomeType; Procedure…

2011/11/5 Michael Van Canneyt :

Show quoted text 18 lines
Procedure SomeOuter; Var  d,e,f : SomeType;  Procedure SomeInner(targetobject:ttargetobject;a:integer;b:someobject;c:string)   begin      targetobject.destinationprocedure(a,b,c);   end; begin  Targethread.queue(@SomeInner(aobject,d,e,f)); end; No difference with 'closure', except more readable. Michael.

I doubt that this would even compile. Also As I pointed out already the example was wrong, the procedure does not have any arguments, the closure must be "closed over" these variables.

and this:

begin
  Targethread.queue(@SomeInner);
end;

would compile but it would just pass the procedure variable. This is not a closure. How is the other thread supposed to know the values of the variables that existed only in the scope of SomeOuter?

A closure would be something like this:

Procedure SomeOuter;
Var
  d,e,f : SomeType;
  Procedure SomeInner
  begin
    targetobject.destinationprocedure(a,b,c);
  end;
begin
  Targethread.queue(SomeInner);
end;

The compiler would need to create an object on the heap containing the procedure *along* with the needed variables a,b,c and then pass the entire object. The receiving side could then call this method and it would still have access to these variables.

A closure has enclosed variables from the surrounding scope where it was created, hence the name 'closure'. You cannot do this with a procedure variable alone, you need an object on the heap to contain the enclosed variables. The Delphi compiler will behind the scenes create a reference counted object with an 'invoke' method (the procedure SomeInner) and all its needed variables.

It is basically a syntactic shortcut to explicitly defining this class, and creating an instance of it.

Reply by email

Michael Van Canneyt
to Bernd
Bernd wrote 10 lines
A closure has enclosed variables from the surrounding scope where it was created, hence the name 'closure'. You cannot do this with a procedure variable alone, you need an object on the heap to contain the enclosed variables. The Delphi compiler will behind the scenes create a reference counted object with an 'invoke' method (the procedure SomeInner) and all its needed variables. It is basically a syntactic shortcut to explicitly defining this class, and creating an instance of it.

I understand all that. That's not the issue.

I didn't mean to say that my example will work with the compiler NOW. Obviously, it would need some extension of the compiler to implement closures.

The only thing I am arguing is that the syntax could have been more clear. Definining a function inside code (or as an argument to another function) is just not Pascal; It goes against everything Pascal stands for.

You could perfectly explicitly declare the closure function outside the code block it is used in, as long as it is AFTER the variables it would need from the outer scope. That is what I wanted to show with my snippet of code. Probably you'd need some kind of extra keyword to distinguish it from 'normal' nested functions.

I am not against closure functionality, although I highly doubt it is *that* useful as some people make it out to be. Even so, I use it in my Javascript programming.

But in Pascal, I would like to see it implemented in a way that doesn't go against Pascal philosophy. In that regard, I consider the way that Borland/CodeGear/Embarcadero implemented it a monstrosity. It simply hurts the eyes...

Michael.

Reply by email

Bernd
to Michael Van Canneyt

2011/11/6 Michael Van Canneyt :

I am not against closure functionality, although I highly doubt it is *that* useful as some people make it out to be. Even so, I use it in my Javascript programming.

I'm also not entirely sure about the necessity of closures in OP, but I must admit I am not totally against it. I am somewhat undecided. Since we have objects we can easily port every algorithm that needs closures 1:1 to OP without changing anything, we just have to put a ton of type definition boilerplate in front of it but the algorithm itself will look and work 100% the same. It will just pass objects around instead of closures (and in some simple cases where we don't need to enclose data we can take the shortcut and use a procedure variable).

In Javascript there is no difference between 'object' and 'function', they are the same thing, every function is an object, creating functions and passing them around is a totally normal thing in JS, just as normal as it is in OP to create Instances of classes and pass them around.

But I cannot totally deny that closures in OP would be a cool feature. They are not necessary to do what can already be done but they still would be an extremely cool feature which can increase the expression/noise ratio significantly in some cases if used appropriately.

And I believe eventually they will be implemented in FPC. I have absolutely no doubt.

BTW: Here is a post I found while googling for Delphi examples, he explains the approach they took in Delphi:
http://compilers.iecc.com/comparch/article/09-04-067

Reply by email

Florian Klämpfl
to Alexander Shishkin: 06.11.2011 1:46, Michael Van Canneyt пишет: Closures can be returned as a function…
Alexander Shishkin wrote 47 lines
06.11.2011 1:46, Michael Van Canneyt пишет: > > > On Sat, 5 Nov 2011, Bernd wrote: > >> 2011/10/25 : >> >>>> targethread.queue( >>>> procedure(targetobject:ttargetobject;a:integer;b:someobject;c:string) >>>> begin >>>> targetobject.destinationprocedure(a,b,c); >>>> end; >>>> >>>> Note how common this looks compared to the original. >>> >>> One point is that you could do the above with a local (and named) >>> procedure >>> as well, and still have all the context. At the very least you would >>> not be >>> raping pascal's readability by putting a >>> complete procedure declaration inside a code block. >> >> How would you preserve the context without finding some place >> somewhere (on the heap) to store the current values of a, b, and c? >> > > Procedure SomeOuter; > > Var > d,e,f : SomeType; > > Procedure > SomeInner(targetobject:ttargetobject;a:integer;b:someobject;c:string) > begin > targetobject.destinationprocedure(a,b,c); > end; > > begin > Targethread.queue(@SomeInner(aobject,d,e,f)); > end; > > No difference with 'closure', except more readable. > Closures can be returned as a function result but nested procedure not (more strictly, this can be complied but will not work because of lifetime of nested procedure).

Of course, but what Michael means is: closure support does not require necessarily anonymous proceudures/functions/methods.

It would be probably more clear to write and this more pascalish:

Procedure SomeOuter;
Var
  d,e,f : SomeType;
  Lambda Procedure
SomeInner(targetobject:ttargetobject;a:integer;b:someobject;c:string)
  begin
     targetobject.destinationprocedure(a,b,c);
  end;
begin
  Targethread.queue(@SomeInner(aobject,d,e,f));
end;

We don't need lambda expressions after all to implement controll statements like e.g. smalltalk.

Reply by email

Alexander Shishkin
to Florian Klämpfl

06.11.2011 15:53, Florian Klämpfl пишет:

Show quoted text 76 lines
Am 05.11.2011 22:58, schrieb Alexander Shishkin: > 06.11.2011 1:46, Michael Van Canneyt пишет: >> >> >> On Sat, 5 Nov 2011, Bernd wrote: >> >>> 2011/10/25: >>> >>>>> targethread.queue( >>>>> procedure(targetobject:ttargetobject;a:integer;b:someobject;c:string) >>>>> begin >>>>> targetobject.destinationprocedure(a,b,c); >>>>> end; >>>>> >>>>> Note how common this looks compared to the original. >>>> >>>> One point is that you could do the above with a local (and named) >>>> procedure >>>> as well, and still have all the context. At the very least you would >>>> not be >>>> raping pascal's readability by putting a >>>> complete procedure declaration inside a code block. >>> >>> How would you preserve the context without finding some place >>> somewhere (on the heap) to store the current values of a, b, and c? >>> >> >> Procedure SomeOuter; >> >> Var >> d,e,f : SomeType; >> >> Procedure >> SomeInner(targetobject:ttargetobject;a:integer;b:someobject;c:string) >> begin >> targetobject.destinationprocedure(a,b,c); >> end; >> >> begin >> Targethread.queue(@SomeInner(aobject,d,e,f)); >> end; >> >> No difference with 'closure', except more readable. >> > > Closures can be returned as a function result but nested procedure not > (more strictly, this can be complied but will not work because of > lifetime of nested procedure). Of course, but what Michael means is: closure support does not require necessarily anonymous proceudures/functions/methods. It would be probably more clear to write and this more pascalish: Procedure SomeOuter; Var d,e,f : SomeType; Lambda Procedure SomeInner(targetobject:ttargetobject;a:integer;b:someobject;c:string) begin targetobject.destinationprocedure(a,b,c); end; begin Targethread.queue(@SomeInner(aobject,d,e,f)); end; We don't need lambda expressions after all to implement controll statements like e.g. smalltalk. _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

OK, agreed, this is more readable than Delphi syntax. But ...
1) If we implement lamdas is FPC we will have to support Delphi syntax.
2) lambda systax is usually as short as possible, but this is not "pascalish".

Reply by email

Bernd
to Florian Klämpfl: Of course, but what Michael means is: closure support does not require necessarily…

2011/11/6 Florian Klämpfl :

Show quoted text 16 lines
It would be probably more clear to write and this more pascalish: Procedure SomeOuter; Var  d,e,f : SomeType;  Lambda Procedure SomeInner(targetobject:ttargetobject;a:integer;b:someobject;c:string)  begin     targetobject.destinationprocedure(a,b,c);  end; begin  Targethread.queue(@SomeInner(aobject,d,e,f)); end;

Why would this function have an argument list? How would the target thread call it?

Reply by email

dmitry boyarintsev
to Alexander Shishkin: 06.11.2011 15:53, Florian Klämpfl пишет: OK, agreed, this is more readable than…
Alexander Shishkin wrote
OK, agreed, this is more readable than Delphi syntax. But ... 1) If we implement lamdas is FPC we will have to support Delphi syntax.

Hi-jacking, the thread, and again should FPC chase Delphi forever? Their technical decisions are directed mostly by "marketing" needs. Should Open Source mimic that?
Now, FPC has provided support for ObjC interface, and Delphi is using that, so maybe it will (and should) be otherwise - Delphi is to provide syntax support for FPC?

thanks,
Dmitry

P.S. a lot of syntax sugar might cause diabetes.

Reply by email

Jonas Maebe
to dmitry boyarintsev
dmitry boyarintsev wrote
Hi-jacking, the thread, and again should FPC chase Delphi forever?

If we want to offer compatibility with source code written for Delphi, which does happen to be one of FPC's project goals, then yes, we do have to do that to some extent.

Now, FPC has provided support for ObjC interface, and Delphi is using that,

Delphi is only using it for iOS (because they don't have their own ARM compiler yet). They are using a different way to interface with Objective-C that does not use the FPC syntax with their Mac OS X compiler. In fact, they reportedly do it without extending the language in any way, by basing it on dynamic dispatch similar to COM interfaces. That in itself is a good argument for not adopting FPC's syntax: if you can do something without extending the language, it's almost always the better option.

so maybe it will (and should) be otherwise - Delphi is to provide syntax support for FPC?

What Delphi /should/ do is a useless discussion on the FPC lists. If you insist on doing it anyway, please move it to fpc-other.

Jonas

Reply by email

Alexander Shishkin
to dmitry boyarintsev: Hi-jacking, the thread, and again should FPC chase Delphi forever? Their technical…

06.11.2011 18:13, dmitry boyarintsev пишет:

Show quoted text 7 lines
On Sun, Nov 6, 2011 at 8:00 AM, Alexander Shishkin wrote: > OK, agreed, this is more readable than Delphi syntax. But ... > 1) If we implement lamdas is FPC we will have to support Delphi syntax. Hi-jacking, the thread, and again should FPC chase Delphi forever? Their technical decisions are directed mostly by "marketing" needs. Should Open Source mimic that?

FPC support not their decisions but existing Delphi code. This is the propose of several syntax modes in FPC as I understand. Even if Delphi will eventually support FPC dialect it have to maintain compatibility with current Delphi dialect and also FPC should do so.

Show quoted text 7 lines
Now, FPC has provided support for ObjC interface, and Delphi is using that, so maybe it will (and should) be otherwise - Delphi is to provide syntax support for FPC? thanks, Dmitry

Reply by email

Florian Klämpfl
to dmitry boyarintsev: Hi-jacking, the thread, and again should FPC chase Delphi forever? Their technical…
dmitry boyarintsev wrote 5 lines
On Sun, Nov 6, 2011 at 8:00 AM, Alexander Shishkin wrote: > OK, agreed, this is more readable than Delphi syntax. But ... > 1) If we implement lamdas is FPC we will have to support Delphi syntax. Hi-jacking, the thread, and again should FPC chase Delphi forever?

You mix here result and goal. If FPC supports new Delphi constructs depends on the fact if somebody provides a patch. No more, no less.

Just as an example: if somebody provides patches to support Extended Pascal, FPC will support Extended Pascal, nobody did so in >15 years. Result: FPC supports no Extended Pascal features.

Reply by email

Jürgen Hestermann
to Florian Klämpfl
Am 06.11.2011 15:13, schrieb dmitry boyarintsev: > Hi-jacking, the thread, and again should FPC chase Delphi forever? You mix here result and goal. If FPC supports new Delphi constructs depends on the fact if somebody provides a patch. No more, no less.

I have the same feeling as Dmitry: There must be a time when FPC does not run after Delphi. Why not now? Other changes were rejected too.

Just as an example: if somebody provides patches to support Extended Pascal, FPC will support Extended Pascal, nobody did so in >15 years. Result: FPC supports no Extended Pascal features.

Actually the question is: *If* someone is investing time into something is this a useful investment? Or wouldn't it be be better to invest this time into other things, i.e. bug fixes?

Also, implementing all existing language constructs from all other languages into Pascal makes it a monster that no one can handle anymore. Supporting Delphi code sounds good in the first place but in the end it bloats the language to something completely different than was intended. The reasons for the success of Pascal were simplicity and clarity. But now it going into the opposite direction. Introducing new constructs over and over again does not make a language easier to use, just the opposite.

Someone who starts programming in Pascal today has the same (or even worse) learning curve than for all other languages. That is not good IMO.

Reply by email

Florian Klämpfl
to Jürgen Hestermann
Jürgen Hestermann wrote 8 lines
Florian Klämpfl schrieb: > Am 06.11.2011 15:13, schrieb dmitry boyarintsev: >> Hi-jacking, the thread, and again should FPC chase Delphi forever? > You mix here result and goal. If FPC supports new Delphi constructs > depends on the fact if somebody provides a patch. No more, no less. I have the same feeling as Dmitry: There must be a time when FPC does not run after Delphi. Why not now?

Feel free to start a fork and we will see what will make it into trunk.

Other changes were rejected too.

Yes. We reject patches to turn FPC into an OS, a C compiler or a coffee machine. No, wait, I think we would accept the last one.

Show quoted text 9 lines
> Just as an example: if somebody provides patches to support Extended > Pascal, FPC will support Extended Pascal, nobody did so in >15 years. > Result: FPC supports no Extended Pascal features. Actually the question is: *If* someone is investing time into something is this a useful investment? Or wouldn't it be be better to invest this time into other things, i.e. bug fixes?

This is everybody's decision. You decided also to write a lengthy mail instead of submitting a patch to a bug report as well while the patch would be much more usefull in my eyes.

Reply by email

Jürgen Hestermann
to Florian Klämpfl
> I have the same feeling as Dmitry: There must be a time when FPC does > not run after Delphi. Why not now? Feel free to start a fork and we will see what will make it into trunk.

Sorry, but I don't know what you are talking about. Isn't it you (and a few others) who decide what becomes part of FPC? It's not a democratic vote, isn't it?

> Other changes were rejected too. Yes. We reject patches to turn FPC into an OS, a C compiler or a coffee machine. No, wait, I think we would accept the last one.

But *you* are deciding this, not?

This is everybody's decision. You decided also to write a lengthy mail instead of submitting a patch to a bug report as well while the patch would be much more usefull in my eyes.

Sorry, I don't know how to submit a patch. Forgive me if I am not on the same knowledge level as you on FPC.

Reply by email

Jonas Maebe
to Jürgen Hestermann
Jürgen Hestermann wrote 6 lines
Florian Klämpfl schrieb: >> I have the same feeling as Dmitry: There must be a time when FPC does >> not run after Delphi. Why not now? > Feel free to start a fork and we will see what will make it into trunk. Sorry, but I don't know what you are talking about. Isn't it you (and a few others) who decide what becomes part of FPC? It's not a democratic vote, isn't it?

That's exactly what he said: you are free to create a fork (= take the FPC source code and do whatever you want with it), and then the currently active FPC developers are also free to take whichever of your patches they consider useful. What's not possible is that other people dictate what you must do with the FPC source code, just like you can't dictate what other people must do.

I don't know how to submit a patch.

http://wiki.freepascal.org/Creating_A_Patch (it was written for Lazarus, but it works pretty much the same with FPC)

Jonas

Reply by email

Florian Klämpfl
to Jürgen Hestermann: Sorry, but I don't know what you are talking about. Isn't it you (and a few others) who…
Jürgen Hestermann wrote 8 lines
Florian Klämpfl schrieb: >> I have the same feeling as Dmitry: There must be a time when FPC does >> not run after Delphi. Why not now? > Feel free to start a fork and we will see what will make it into trunk. Sorry, but I don't know what you are talking about. Isn't it you (and a few others) who decide what becomes part of FPC? It's not a democratic vote, isn't it?

Will you organize democratic votes in the future on rejected patches?

Remember though, there is something like a consititution:
- FPC is a pascal compiler written in pascal.
- Patches may break old code as little as possible and cause no regressions in the regression tests.

If you don't like this, you should fork FPC. Though we can discuss to change the first sentence into
- FPC is a compiler written in pascal for wirthian languages. But to do so, somebody has really to prove it's commitment over years.

Show quoted text 7 lines
>> Other changes were rejected too. > Yes. We reject patches to turn FPC into an OS, a C compiler or a coffee > machine. No, wait, I think we would accept the last one. But *you* are deciding this, not?

Yes, because nobody did yet volunteer to setup and maintain the structure to organize votes on rejected patches. Probably also because their number is too low.

Show quoted text 8 lines
> This is everybody's decision. You decided also to write a lengthy mail > instead of submitting a patch to a bug report as well while the patch > would be much more usefull in my eyes. Sorry, I don't know how to submit a patch. Forgive me if I am not on the same knowledge level as you on FPC.

Read the handbook of your browser how to upload files if a website contains such a field. Then go to the issue report in the bug tracker and upload the patch.

Reply by email

Martin Schreiber
to Jürgen Hestermann: I have the same feeling as Dmitry: There must be a time when FPC does not run after…
Jürgen Hestermann wrote 10 lines
Also, implementing all existing language constructs from all other languages into Pascal makes it a monster that no one can handle anymore. Supporting Delphi code sounds good in the first place but in the end it bloats the language to something completely different than was intended. The reasons for the success of Pascal were simplicity and clarity. But now it going into the opposite direction. Introducing new constructs over and over again does not make a language easier to use, just the opposite.

Agreed 100%. If someone wants to write Delphi and FPC compatible code this is already possible.
I don't understand why FPC should become a 100% Delphi clone instead the "best general software development environment ever" for the only purpose that Delphi users have a free cross platform alternative without to care about FPC compatibility while writing their Delphi code.
I propose to make a review of current and future FPC language constructs and to classify the constructs into different groups (Pascal kernel, OOP kernel, convenience, syntax sugar, can be replaced by, code bloat, Delphi clone...). Eh.., no, I can't do it my self because I don't know all the newer possibilities and there is another FPC related open source project which needs my attention. ;-)
People who want to write code which is understandable by every Pascal coder can limit their use of constructs to the basic groups. It even will be possible to make a streamlined FPC version later without the bloated elements.

Martin

Reply by email

Jonas Maebe
to Martin Schreiber
Martin Schreiber wrote 7 lines
I don't understand why FPC should become a 100% Delphi clone instead the "best general software development environment ever" for the only purpose that Delphi users have a free cross platform alternative without to care about FPC compatibility while writing their Delphi code.

One reason is to make it easy for FPC users to reuse existing Delphi code that is out there without having to rewrite it in an "FPC- compatible way".

Jonas

Reply by email

Martin Schreiber
to Jonas Maebe
Jonas Maebe wrote 13 lines
On 07 Nov 2011, at 08:10, Martin Schreiber wrote: > I don't understand why FPC should become a 100% Delphi clone instead > the "best > general software development environment ever" for the only purpose > that > Delphi users have a free cross platform alternative without to care > about FPC > compatibility while writing their Delphi code. One reason is to make it easy for FPC users to reuse existing Delphi code that is out there without having to rewrite it in an "FPC- compatible way".

Is there a big demand? Examples? Because I write most of the code myself I don't know the market well.
Maybe if FPC clearly states that it will not follow Delphi blindly and defines what Delphi devels must do to be FPC compatible and to have the free multi platform alternative there will be more FPC/Delphi compatible code? Now where Embarcadero uses FPC for iOS development is probably a good moment to do so.

Martin

Reply by email

Jonas Maebe
to Martin Schreiber
Martin Schreiber wrote 7 lines
On Monday 07 November 2011 10.55:41 Jonas Maebe wrote: > On 07 Nov 2011, at 08:10, Martin Schreiber wrote: > One reason is to make it easy for FPC users to reuse existing Delphi > code that is out there without having to rewrite it in an "FPC- > compatible way". > Is there a big demand? Examples?

Indy and Synapse are two I know of, but there are probably many more. I also used FPC/Lazarus to port an architectural simulator developed in our group at the university a long time ago (using Delphi 5 or so) to Mac and Linux. I was relatively easy, even though I had no prior experience with developing GUI applications in Lazarus (and still don't really have, actually, since most things just compiled and worked barring some widgetset bugs).

Maybe if FPC clearly states that it will not follow Delphi blindly

We will not do that. Just like we won't say that we will follow them blindly. What happens depends on what code people write, which patches are submitted and what the quality and impact of those patches is. A lot of Delphi-compatibility features have been added to the compiler in the past year simply because Paul Ishenin cares about that and he generally writes good code and tests. And non-Delphi compatible features such as Objective-Pascal and a JVM backend have been added because I cared about that.

and defines what Delphi devels must do to be FPC compatible and to have the free multi platform alternative there will be more FPC/Delphi compatible code?

In general that means limiting themselves to features of Delphi versions from a couple of years back, and not using Windows-specific code.

Now where Embarcadero uses FPC for iOS development is probably a good moment to do so.

I doubt it, because
a) Embarcadero are working on their own ARM compiler and won't ship FPC anymore with future Delphi versions
b) all example code posted by FPC contains every single line of implementation code between {$ifdef FPC} to make it clear that you may have to rewrite that code in the future (although strangely enough they use {$mode objfpc} instead of {$mode delphi} everywhere in that code)

Jonas

Reply by email

Luiz Americo Pereira Camara
to Martin Schreiber: Is there a big demand? Examples? Because I write most of the code myself I don't know the…
Martin Schreiber wrote 11 lines
> One reason is to make it easy for FPC users to reuse existing Delphi > code that is out there without having to rewrite it in an "FPC- > compatible way". > Is there a big demand? Examples?

I speak only for myself.

This is a component that i'd like to see compiled with fpc

http://code.google.com/p/emballo/

The problems
- generic support: bugs.freepascal.org/view.php?id=20503 . Can be workaround by type casting
- reflection/rtti support to call constructor of a given TClass. Can be work around by registering a function that returns an instance or using AfterConstruction to setup object instead of the constructor directly

BTW: i will take the old version version of emballo and rewrite it in an "FPC compatible way" to get things done in the meantime.

Looking also to http://code.google.com/p/delphi-spring-framework/ and http://code.google.com/p/delphi-orm/

Luiz

Reply by email

Martin Schreiber
to Luiz Americo Pereira Camara
Luiz Americo Pereira Camara wrote 21 lines
> Is there a big demand? Examples? I speak only for myself. This is a component that i'd like to see compiled with fpc http://code.google.com/p/emballo/ The problems - generic support: bugs.freepascal.org/view.php?id=20503 . Can be workaround by type casting - reflection/rtti support to call constructor of a given TClass. Can be work around by registering a function that returns an instance or using AfterConstruction to setup object instead of the constructor directly BTW: i will take the old version version of emballo and rewrite it in an "FPC compatible way" to get things done in the meantime. Looking also to http://code.google.com/p/delphi-spring-framework/ and http://code.google.com/p/delphi-orm/

So probably there are at least two different expectations into FPC which can't be fulfilled both: "best general purpose software development environment ever" and "100% current Delphi compatibility".

Martin

Reply by email

Jürgen Hestermann
to Jonas Maebe: That's exactly what he said: you are free to create a fork (= take the FPC source code…
That's exactly what he said: you are free to create a fork (= take

the FPC source code and do whatever you want with it), and then the currently active FPC developers are also free to take whichever of your patches they consider useful. What's not possible is that other people dictate what you must do with the FPC source code, just like you can't dictate what other people must do.

This argument is pulled out each time someone suggest things that the main developers don't like. But despite from the work this requires it would result in my own island solution. It cannot be the goal that thousands of people spawn their own Pascal dialect. I don't think that anybody is wanting this. I thought this open source project is about having a *public* Pascal language which can be discussed and argued about. I know that there will be no common sense about each and every topic but it should be possible to say opinions which possibly make others change their mind (or not).

Reply by email

Marco van de Voort
to Martin Schreiber: So probably there are at least two different expectations into FPC which can't be…

In our previous episode, Martin Schreiber said:

So probably there are at least two different expectations into FPC which can't be fulfilled both: "best general purpose software development environment ever" and "100% current Delphi compatibility".

That "current" is added by you. FPC strives to do that of course, but never had the illusion it was near enough to claim something like that. Not now, and not in the past.

Reply by email

Jonas Maebe
to Jürgen Hestermann: the FPC source code and do whatever you want with it), and then the currently active FPC…
Jürgen Hestermann wrote
Jonas Maebe schrieb: > That's exactly what he said: you are free to create a fork (= take the FPC source code and do whatever you want with it), and then the currently active FPC developers are also free to take whichever of your patches they consider useful. What's not possible is that other people dictate what you must do with the FPC source code, just like you can't dictate what other people must do. > This argument is pulled out each time someone suggest things that the main developers don't like. But despite from the work this requires it would result in my own island solution. It cannot be the goal that thousands of people spawn their own Pascal dialect. I don't think that anybody is wanting this. I thought this open source project is about having a *public* Pascal language which can be discussed and argued about. I know that there will be no common sense about each and every topic but it should be possible to say opinions which possibly make others change their mind (or not).

The problem is that the work needs to be done. And once it is done, it needs to be maintained, and must impact other potential work as little as possible. Because of these reasons a) people who implement stuff have way more influence than people who only voice their opinion about what/how something should be implemented b) people who have already implemented lots of stuff have more influence than people who have not done that

It's not that longtime developers won't listen to other opinions, but they do have the final say. Without such a dynamic, the project simply cease to exist. After all, without the people who do the work there is nothing at all, not even a project going into a direction that you don't like.

The reason that this argument is always used is simply because that is simply how it is. You can argue that it should be different, but really the only way to do that is to do the work yourself. That may well be an uphill battle if you wish to fundamentally change some things or the development direction of an entire project, in which case starting your own project may be the best option. After all, that would give you the opportunity to demonstrate that your way is actually better and will attract more/better/whatever developers and users, or otherwise will result in something more useful, rather than just arguing that this will be the case and that people should understand that.

Jonas

Reply by email

Jürgen Hestermann
to Jonas Maebe
>> That's exactly what he said: you are free to create a fork > This argument is pulled out each time someone suggest things that

the main developers don't like.

The reason that this argument is always used is simply because that

is simply how it is.

I know that. But still: Why is this argument used like a knee-jerk reaction as soon as someone writes unliked opinions? That's like saying: "Stop critisizing me. I don't like this. I am the boss!". If you don't like to write facts/reasons then don't say anything but using your thought-terminating cliché over and over again just makes you sound arrogant.

It's not that longtime developers won't listen to other opinions,

But that's what you do when using your standard argument.

Reply by email

Graeme Geldenhuys
to Marco van de Voort: In our previous episode, Martin Schreiber said: That "current" is added by you. FPC…
Marco van de Voort wrote
That "current" is added by you. FPC strives to do that of course, but never had the illusion it was near enough to claim something like that. Not now, and not in the past.

So what exactly is the goals of FPC then? And please don't tell me "delphi compatible" because then you need to tell me which version of Delphi - and I doubt you can.

As a core developer of FPC can yo please summarize in one or two sentences the actual goal of FPC - that way we are all on the same page.

Regards,   - Graeme - _______________________________________________ fpGUI - a cross-platform Free Pascal GUI toolkit http://fpgui.sourceforge.net

Reply by email

Florian Klaempfl
to Jürgen Hestermann: the main developers don't like. is simply how it is. I know that. But still: Why is this…
Jürgen Hestermann wrote 9 lines
Jonas Maebe schrieb: >>> That's exactly what he said: you are free to create a fork >> This argument is pulled out each time someone suggest things that the main developers don't like. > The reason that this argument is always used is simply because that is simply how it is. I know that. But still: Why is this argument used like a knee-jerk reaction as soon as someone writes unliked opinions?

The opinion is not unliked but just useless and wastes the time of people who try to use this mailing list to support others using fpc. If you want to express opinions again and again without any consequences like coming up with code just write a blog. You know, "talk is cheap, show me the code" (Thorvalds).

Reply by email

Florian Klaempfl
to Graeme Geldenhuys: So what exactly is the goals of FPC then? And please don't tell me "delphi compatible"…
Graeme Geldenhuys wrote 13 lines
On 7 November 2011 20:41, Marco van de Voort wrote: > > That "current" is added by you. FPC strives to do that of course, but never > had the illusion it was near enough to claim something like that. Not now, > and not in the past. So what exactly is the goals of FPC then? And please don't tell me "delphi compatible" because then you need to tell me which version of Delphi - and I doubt you can. As a core developer of FPC can yo please summarize in one or two sentences the actual goal of FPC - that way we are all on the same page.

Let me answer:
Writing an (L)GPL'ed pascal (*) compiler being self hosting.

(*) pascal might be replaced by 'wirthian languages' if someone with a
lot of commitment over years pops up and works on this.

Reply by email

Graeme Geldenhuys
to Florian Klaempfl
Florian Klaempfl wrote
Let me answer: Writing an (L)GPL'ed pascal (*) compiler being self hosting.
From the man himself. OK good, so now we all know the goal is not one

of "delphi compatible" (that is rather limited only as a side effect - nice to have), so please all core developers, stop using that as an excuse to stop other FPC innovation. Over the years I have heard many features being declined because they will "not be delphi compatible".

Regards,   - Graeme - _______________________________________________ fpGUI - a cross-platform Free Pascal GUI toolkit http://fpgui.sourceforge.net

Reply by email

Tomas Hajny
to Graeme Geldenhuys
Graeme Geldenhuys wrote 11 lines
On 8 November 2011 09:23, Florian Klaempfl wrote: > > Let me answer: > Writing an (L)GPL'ed pascal (*) compiler being self hosting. From the man himself. OK good, so now we all know the goal is not one of "delphi compatible" (that is rather limited only as a side effect - nice to have), so please all core developers, stop using that as an excuse to stop other FPC innovation. Over the years I have heard many features being declined because they will "not be delphi compatible".

Examples?

Tomas

Reply by email

Martin Schreiber
to Graeme Geldenhuys: of "delphi compatible" (that is rather limited only as a side effect - nice to have), so…
Graeme Geldenhuys wrote 10 lines
On 8 November 2011 09:23, Florian Klaempfl wrote: > Let me answer: > Writing an (L)GPL'ed pascal (*) compiler being self hosting. > >From the man himself. OK good, so now we all know the goal is not one of "delphi compatible" (that is rather limited only as a side effect - nice to have), so please all core developers, stop using that as an excuse to stop other FPC innovation. Over the years I have heard many features being declined because they will "not be delphi compatible".

I fear the opposite: all Delphi "crap" will be implemented.

Martin

Reply by email

Graeme Geldenhuys
to Tomas Hajny: Examples? Tomas

2011/11/8 Tomas Hajny :

Examples?

I can list them all, but I'm not going to waist my time on them again. Search the mailing list or Mantis.

But to humour you, here is just one of many examples: THelpEvent in the RTL. I proposed a patch to change it to be more in line with FPC's goals [being a cross-platform compiler, so requires cross-platform solutions]. The change was declined because THelpEvent is a direct copy of Delphi's equivalent, and even worse, is very Windows specific in its signature. Yes, it's a small and stupid example, but there are many more like this. Delphi-compatibility seems to trump everything else (as Martin said).

Regards,   - Graeme - _______________________________________________ fpGUI - a cross-platform Free Pascal GUI toolkit http://fpgui.sourceforge.net

Reply by email

Marco van de Voort
to Martin Schreiber: I fear the opposite: all Delphi "crap" will be implemented. Martin

In our previous episode, Martin Schreiber said:

Show quoted text 5 lines
> nice to have), so please all core developers, stop using that as an > excuse to stop other FPC innovation. Over the years I have heard many > features being declined because they will "not be delphi compatible". I fear the opposite: all Delphi "crap" will be implemented.

Don't worry, there is also room for FPC "crap" ("case string of" e.g.) :-)

Reply by email

Tomas Hajny
to Graeme Geldenhuys: 2011/11/8 Tomas Hajny : I can list them all, but I'm not going to waist my time on them…
Graeme Geldenhuys wrote 15 lines
2011/11/8 Tomas Hajny : > > Examples? I can list them all, but I'm not going to waist my time on them again. Search the mailing list or Mantis. But to humour you, here is just one of many examples: THelpEvent in the RTL. I proposed a patch to change it to be more in line with FPC's goals [being a cross-platform compiler, so requires cross-platform solutions]. The change was declined because THelpEvent is a direct copy of Delphi's equivalent, and even worse, is very Windows specific in its signature. Yes, it's a small and stupid example, but there are many more like this. Delphi-compatibility seems to trump everything else (as Martin said).

This is a nice example of my reason for asking. What you list here is not a new feature but change to something what was created in order to provide Delphi compatibility in the first place. Extending such stuff should be possible (and has been done many times), changing it by breaking the compatibility is not necessarily such a good idea.

On the other hand, I don't think that new features are being rejected because they may add something not available in Delphi (FPC already provides features not available in Delphi and there is no reason why more of them shouldn't be added - if they are reasonable and there are people willing to implement and maintain them.

Tomas

Reply by email

Florian Klaempfl
to Graeme Geldenhuys: 2011/11/8 Tomas Hajny : I can list them all, but I'm not going to waist my time on them…
Graeme Geldenhuys wrote 15 lines
2011/11/8 Tomas Hajny : > > Examples? I can list them all, but I'm not going to waist my time on them again. Search the mailing list or Mantis. But to humour you, here is just one of many examples: THelpEvent in the RTL. I proposed a patch to change it to be more in line with FPC's goals [being a cross-platform compiler, so requires cross-platform solutions]. The change was declined because THelpEvent is a direct copy of Delphi's equivalent, and even worse, is very Windows specific in its signature. Yes, it's a small and stupid example, but there are many more like this. Delphi-compatibility seems to trump everything else (as Martin said).

So you wanted to break existing stuff other people probably used? It is indeed one of FPC's policy to avoid breakage of exisiting code.

Or did you propose a TFPHelpEvent?

Reply by email

Martin Schreiber
to Marco van de Voort: In our previous episode, Martin Schreiber said: Don't worry, there is also room for FPC…
Marco van de Voort wrote 8 lines
In our previous episode, Martin Schreiber said: > > nice to have), so please all core developers, stop using that as an > > excuse to stop other FPC innovation. Over the years I have heard many > > features being declined because they will "not be delphi compatible". > > I fear the opposite: all Delphi "crap" will be implemented. Don't worry, there is also room for FPC "crap" ("case string of" e.g.) :-)

Which I like but not use because of Delphi 7 compatibility. :-)

Martin

Reply by email

Graeme Geldenhuys
to Florian Klaempfl: So you wanted to break existing stuff other people probably used? It is indeed one of…
Florian Klaempfl wrote
So you wanted to break existing stuff other people probably used? It is indeed one of FPC's policy to avoid breakage of exisiting code.

Break what existing code? I searched all of FPC, Lazarus, Lazarus CCR and MSEgui - there was no existing usage of THelpEvent. Lazarus's LCL implements there own version of this. So I really didn't see an issue in changing it in FPC. If you (or Marco - the one that declined my proposal the first time round) have an example where it would break existing code, I would love to know about those please.

Now if you want to go down the "delphi compatibility" route, well then FPC is in the wrong anyway! Neither Delphi, nor Kylix has THelpEvent defined in the Classes unit, but rather in the Forms.pas unit. So what delphi is FPC really trying to be compatible with in this case?

Or did you propose a TFPHelpEvent?

I can't remember the details, but I think I proposed that too. In the end, I simply defined what I needed in fpGUI itself. Clearly the latter is the path of least resistance (Martin should agree with his experiences of MSEgui) - though I do prefer to use existing classes from FPC (as a first option).

As I said, in the end I defined what I needed in fpGUI itself, using existing types in the signature, like THelpType and THelpContext - which ARE both defined in the RTL, doesn't reek of Windows'ism.

  TfpgHelpEvent = function(AHelpType: THelpType; AHelpContext: THelpContext;
       const AHelpKeyword: String; const AHelpFile: String;
       var AHandled: Boolean): Boolean of object;
Regards,   - Graeme - _______________________________________________ fpGUI - a cross-platform Free Pascal GUI toolkit http://fpgui.sourceforge.net

Reply by email

Arioch
to Florian Klämpfl: For such applications one uses procedure variables in pascal. I still don't see why this…

Florian Klämpfl wrote

Show quoted text 11 lines
>> This is the prototypical way to run a function over each element in a >> collection, returning the results. > (map (lambda (x) (+ x 1)) '(1 2 3)) > -> (2 3 4) 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.

Sorry for resurrecting al thread, but p[erhaps better to keep things together.
1) "anonymous methods" in Delphi are made in very Pascalish way, a lot of wording, a lot of boilerplate.
That adds to readability, but makes their use much harder. If you have relatively complex 4-5 lines function, then the overhead is slightly noticeable. But such functions are a borderline to me, having them anonymous hampers both ease of read and ease of debug. I know C++ fans how say that begin/end are awfully long. Well, Delphi style of anonymous functions would frighten them even more.

Here we was devised in 1949 to look like Classic
monumental style building, or at least some "manufacturing plant" style building made of bricks industrial way.
Functional style is like more like elegant houses made of paper and thin plywood, something mayeb of Gothic or Japanese style, easily constructible (composable) to any form you like.

They really are hard to make together. You can read about Nemerle and Scala though, about the attempts.

For example in C++ lambdas look total strangers by syntax, but that is inevitable. When you have to type 20 chars of boilerplate for 3 char function "x+y" - that is too much.
http://www.cprogramming.com/c++11/c++11-lambda-closures.html

However, other than that i like syntax for C++ lambda's. It is clearly distinct for compiler, it separates and thus clearly defines captured values, it is rather laconic.

2) however to treat "x+y" as a proper function definition one should have 2.1) either typeless (at compile type, in runtime that may be dynamical typing, duck typing, whatever) language like LISP or Erlang or Python even generic function
2.2) or strongly typed language with very sophisticated type infering like Nemerle and Scala
"x + y" is a function, but the compiler should look at the context and make guess what would be the types for x, y and result (latter would usually be least common type for x and y);
So compiler looks at the context and turns - where appropriate - "x + y" into
a generic "function<TX, TY, TRes> (const x:TX; const y:TY): TRes; begin Result := x+y; end; "
Quite a lot to generate of three symbols.
Well, there are even more concise syntaxes, using jokers or omissions. For example in collection.filter operations the Predicate is expected (it is called collection.Where in Spring4Delphi and MS.Net). So then "_ > 2" or "> 2" would be correct function, implicated to
a generic "function<SomeContextDependantNumericType> function( const value: SCDNT); begin Result := value>2; end;
It would also be nice for compiler to make some merges.

Surely all that cherries can not be gathered without heavy language and compiler reworking.
Delphi tried to get at least some of those, but 1949 legacy feels there. The question is about possible compromise.

(**** Side note: type inferring is also very useful in Generics. ***)
Some very tiny part of it is even implemented in Delphi :-)

Consider { Chu Jetcheng, 2008-07-24 }
http://wiki.freepascal.org/Generics_proposals

var
    Obj1: TGeneric of Integer, Real;
begin
    Obj1 := TGeneric.Create(32, 3.14);

This is quite un-orthodox proposal At the statement, a compiler know the type of Obj1, but does not know the type of TGeneric<X,Y>. Since usually rvalue is parsed with no look at lvalue, such inferring is hardly possible at all. More traditional way would be like

var
    Obj1;
begin
    Obj1 := TGeneric<String, Integer>.Create(32, 3.14);

Where compiler "infers" type of Obj1 looking at the type of value used for assignment.

It is even better if type would be something like
TEvent<String, Record&lt;Field1, Filed2, Array&lt;Items>>>. You may say - make an alias.
Type MyEventHere = TEvent<String, Record&lt;Field1, Filed2, Array&lt;Items>>>.

Sometimes that works, for larger code blocks.
But if you have to declare type for every procedure in your unit, that becomes a mess...

However that is well in the spirit of Wirth.
In 1949 AFAIR you could not have var x: array[0..10] of integer; You should have pre-defined named alias for that array.
And "open arrays" functions parameters of Turbo Pascal 7 would be just a schism and herecy for original Pascal specs.
But we now even have and enjoy dynamic arrays and generalyl do not consider them large enough to have their own dedicated explicitly declared name.

(**** End of Side note. ***)

3) Why that matters ?

You can refactor program with more ease.

Imagine you just want to save some table to... XML file. Or write it to string. Or maybe pass it to some processor, that would check its sanity.

What is the table ? Maybe it is dynamic "array of record ..... end;" ? Or maybe it is TDataSet ? Or maybe it is TStringList.Rows ? Or any of that and who knows what else ?
// that is not that spectacular. TDataSet internals are scarcely documented spaghetti. When soem in-memory dataset no more compiles in newer Delphi you'd want to change it to dynamic array or TList, but that would ask to re-write all the units using it! You would end up using TClientDataSet and all its TField objects just to pass dynamic array to make a single iteration over it and dispose. Okay, in the world of many-GHz many-core CPUs that does not matter. But "while not q.eof do begin ... q.next; end;" loop is a bit fragile and redundant in wording. //

Okay, you also want to filter it. Your user wants to see customers with most sales.
So he enters a number and only wants to see those whose sales are above.

AFAIR TDataSet had some filtering event (or was it TBDEDataSet), array does not and should be copied.
The logic is very different for same purpose again, depending on source data type style.

But what if there then be one more filtering wished ? Or what if consumer program needs to apply its internal filtering as well ?

In hypothetical 100% inferring functional style it could look like

procedure Button1OnClick(...);
var Consumer; Data;
begin
      Data := CurrentConsumersCollection;
// array, file object, TDataSet - whatever
      Consumer := ConsumerArray[RadioGroup1.ItemIndex];
// Save to XML, save to network, show on screen - whatever
      if CheckBox1.checked then
         Data := Data.Filter( _.total > StrToInt(editSalesThreshhold.Text );
      if CheckBox2.checked then
         Data := Data.Filter( _.CityCode = StrToInt(editCityCode.Text );
      .....
     Data.Map(Consumer.StepMethod);
(* or Consumer.Process(Data) *)
end;

This function could potentially work with ANY kind of input data containers.

4) And here we come to "capturing" - why those so called "anonymous methods" are better called "closures", why that C++ \starts lambdas not with "()" par but with two pairs "[] ()".

What is the argument type of
  "     Data := Data.Filter( _.CityCode = StrToInt(editCityCode.Text ); " ?

Obviously it only can be a predicate: function<our-data-record-type> (const value:ODRT): boolean;
Otherwise collection should have some fore-knowledge how it would be used later.

Alternatively, it can also have "pointer" second argument, sending all type checking to sewer.
Just how non-Generic TList is practically done. Brr...

Ahem, but how would it get city code to compare ?
We cannot compile 1000 functions with all the reference values of CityCode. So the function should "capture" value of "StrToInt(editCityCode.Text" from calling place.
In OOP language terms that means we create some object where "StrToInt(editCityCode.Text" is some private field. It is exactly how that is implemented in Delphi - via TInterfacedObject with refcounting.

Compilers sees that the auto-generated function should have StrToInt(editCityCode.Text ) as a parameter from external context. It also knows it is not allowed to have due to argument type of Collection.Filter method being single-argument predicate.
So it behind the hood creates that object with extra parameter like private field.

Other possible approaches ? Well, that FPC wiki page mentions Extended Pascal / GNU Pascal "scheme types", tapes tagged with constant values. That maybe could be extended to be var-tagged.
Then there can be hypothetical "function(code:integer) CompareCityCode(const r: record): boolean" type. If it can somehow be considered derived (okay, assignment-compatible) from mere "function CompareCityCode(...):..." then that would be the same idea mostly.

Most hardcore feature would probably be "partial application", i mentioned Scala but even it has it with limitations.

Imagine we have
function CompareCityCode(const value: our-data-record; const referenceCode:
integer): boolean;
begin Result := value.CityCode = referenceCode; end;

What would be result of "CompareCityCode(?, 10)" ? It could be a predicate, it could be new boolean function, having single argument "value" and always comparing with 10.
In VM-based languages like Lisp or Java/.Net that can indeed be implemented as function generator.
In native languages that probably can only be implemented as a hidden object with "10" stored to that private field again.

Why bother ? Well, just imagining how much code and how many functions and names would have be written to implement that spectacular Button1Click with its adapting to different datasources, different consumers, different lists of filters on different conditions, etc.

And then one future day this code - now split to many many dependent procedures and types - have to be reworked.

5) It is hard to implement all that laconic fluid features in "heavy industrial" style language of 1949.
Probably would never happen to Pascal. But some parts, some ideas probably can be implemented still.

For example in Delphi one can not do generic function "x+y" except is both "x" and "y" are classes.
But if they are integers or floats - then compiler cannot make a difference, less so infer the types.
Well, x+y is maybe nonsense, but what about Max(x,y), if it could be implemented generically for any type in single place... Well, again i am passing from lambdas to generics - but their practical use is entangled heavily...

Surely 1949-styled Pascal can not make all that features 1st citizens. The question is how much and in what style of compromise can be implemented. Generics were also heresy for original Pascal. But they are implemented, some in Delphi and to some seemingly less extent in FPC as well.

While i pity divergence of syntaxes between Delphi and FPC generics, i strangle would not pity if FPc finally implement
lambdas/closures/anonymous-methods in non-Delphi style. Since Delphi style is so Pascalish, that it heavily limits their practical use.

View this message in context: http://free-pascal-general.1045716.n5.nabble.com/Delphi-s-anonymous-functions-in-Free-Pascal-tp4911527p5711032.html Sent from the Free Pascal - General mailing list .

Reply by email

Mark Morgan Lloyd
to Arioch
Arioch wrote 6 lines
Here we was devised in 1949 to look like Classic monumental style building, or at least some "manufacturing plant" style building made of bricks industrial way. Functional style is like more like elegant houses made of paper and thin plywood, something mayeb of Gothic or Japanese style, easily constructible (compostable) to any form you like.

I'm curious: where do you get this 1948 date from? I'm not even sure that assemblers (as we know them) existed in 1949...

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Sven Barth
to Arioch: Florian Klämpfl wrote Sorry for resurrecting al thread, but p[erhaps better to keep…
"Arioch" wrote
Surely 1949-styled Pascal can not make all that features 1st citizens. The question is how much and in what style of compromise can be

implemented.

Show quoted text 8 lines
Generics were also heresy for original Pascal. But they are implemented, some in Delphi and to some seemingly less extent in FPC as well. While i pity divergence of syntaxes between Delphi and FPC generics, i strangle would not pity if FPc finally implement lambdas/closures/anonymous-methods in non-Delphi style. Since Delphi style is so Pascalish, that it heavily limits their practical use.

I don't know whether you tested recent versions of FPC, but since 2.6.0 the support for Delphi compatible generics improved, though generic functions/methods and constraints are still missing.

Regards,
Sven

Reply by email

Unknown author
to Arioch: Florian Klämpfl wrote Sorry for resurrecting al thread, but p[erhaps better to keep…
Arioch wrote 24 lines
Florian Klämpfl wrote > > >>> This is the prototypical way to run a function over each element in a >>> collection, returning the results. >> (map (lambda (x) (+ x 1)) '(1 2 3)) >> -> (2 3 4) > > 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. > Sorry for resurrecting al thread, but p[erhaps better to keep things together. 1) "anonymous methods" in Delphi are made in very Pascalish way, a lot of wording, a lot of boilerplate. That adds to readability, but makes their use much harder. If you have relatively complex 4-5 lines function, then the overhead is slightly noticeable. But such functions are a borderline to me, having them anonymous hampers both ease of read and ease of debug. I know C++ fans how say that begin/end are awfully long. Well, Delphi style of anonymous functions would frighten them even more.

I don't think anonymous functions should be added to the are IMHO a negation of what pascal stands for. If your programming style is so strange that you need lamba functions or anonymous functions, then Pascal is simply not for you.

Michael.

Reply by email

Ralf A. Quint
to Unknown author
Show quoted text 7 lines
I don't think anonymous functions should be added to the compiler at all. They are IMHO a negation of what pascal stands for. If your programming style is so strange that you need lamba functions or anonymous functions, then Pascal is simply not for you. Michael.

+1

I think a lot of people need to get back to program in Pascal...

Ralf

Reply by email

Arioch
to Mark Morgan Lloyd: I'm curious: where do you get this 1948 date from? I'm not even sure that assemblers (as…
I'm curious: where do you get this 1948 date from? I'm not even sure that assemblers (as we know them) existed in 1949... Mark Morgan Lloyd

Damn! you're definitely right.
At vwery very least Pascal could not be before Algol-68, which could not be before... ahem.
But now I wonder myself....

????....

Here, found it at last!!!!
look at the picture.
I scanned the 1st number looked like year and it just imprinted without any doubt.
I remember i was slightly surprised like "so early? such a mighty man!" but just imprinted the number and passed by.
I was deep into another theme and year was not important to me, so i just scanned it, noted and went one without single though about possibility.

After all computaiton basis like Turing Machine and Lambda Calculus were developed somewhere around those years. At the moment it did seemes unbelievable but not impossible.

Really, i embarassed myself, thanks for pointing it.

View this message in context: http://free-pascal-general.1045716.n5.nabble.com/Delphi-s-anonymous-functions-in-Free-Pascal-tp4911527p5711050.html Sent from the Free Pascal - General mailing list .

Reply by email

Unknown author
to Ralf A. Quint: +1 I think a lot of people need to get back to program in Pascal... Ralf

+1 - anonymous functions demonstrate a laziness to software design: what you can't name you actually don't design...

----- Mail original -----
De: "Ralf A. Quint"
À: "FPC-Pascal users discussions"
Envoyé: Jeudi 30 Août 2012 09:26:27
Objet: Re: [fpc-pascal] Re: Delphi's anonymous functions in Free Pascal

Show quoted text 7 lines
I don't think anonymous functions should be added to the compiler at all. They are IMHO a negation of what pascal stands for. If your programming style is so strange that you need lamba functions or anonymous functions, then Pascal is simply not for you. Michael.

+1

I think a lot of people need to get back to program in Pascal...

Ralf

Reply by email

Arioch
to Ralf A. Quint: +1 I think a lot of people need to get back to program in Pascal... Ralf

Ralf A. Quint wrote

Show quoted text 5 lines
At 12:09 AM 8/30/2012, michael.vancanneyt@ wrote: >They are IMHO a negation of what pascal stands for. If your programming +1

Well, the same should be told about everything modern pascal is.

Open and dynamic arrays, pointer math, objects, generics, even units. It was all breaking the initial Pascal strictness and rigidness.

Because what was counted "large blocks" deserving their own explicit naming back then - now seems trivial small detail.

Generics are alien to Pascal no more no less than closures.

View this message in context: http://free-pascal-general.1045716.n5.nabble.com/Delphi-s-anonymous-functions-in-Free-Pascal-tp4911527p5711052.html Sent from the Free Pascal - General mailing list .

Reply by email

Arioch
to Sven Barth: implemented. I don't know whether you tested recent versions of FPC, but since 2.6.0 the…

Sven Barth-2 wrote

Show quoted text 7 lines
Am 29.08.2012 22:56 schrieb "Arioch" &lt;;: I don't know whether you tested recent versions of FPC, but since 2.6.0 the support for Delphi compatible generics improved, though generic functions/methods and constraints are still missing.

Thanks. No, i just checked wiki and docs and referenced mailing lists letters. Last time i worked with Lazarus were times of Linux transition from 2.4 to 2.6. Don't recall exactly but that was ooold times :-)

Personally i think that introducing yet more keywords is not good thing, when can be avoided.
But since it was done, i did not think that FPC would both implement their native syntax with generics/specialize keywords and keywordless Delphi style.

Lack of generic methods and corresponded partially to it lack of modern RTTI is pity, but hopefully would be resolved.

PS. Checking available docs, besides, was how i came to the topic and was wondered that no one answered why closures matter.

It is surely personal test to like or dislike them. I already said that they can make code hardly readable and hardly debugable is over-used.
And that Delphi model of them makes them impractical for oneliners (where their true power lies) and only practical for complex routines (where they are problematic)

Howeveri wished that their benefits at least were outlined in the thread, referenced from wiki.

View this message in context: http://free-pascal-general.1045716.n5.nabble.com/Delphi-s-anonymous-functions-in-Free-Pascal-tp4911527p5711054.html Sent from the Free Pascal - General mailing list .

Reply by email

Unknown author
to Arioch: Ralf A. Quint wrote Well, the same should be told about everything modern pascal is. Open…

I beg to differ. Read Niklaus' work on why he created Pascal: two objectives stand out : readability and ease-of-compiling. He wrote explicitly he wanted a language he could easily write his compiler in...

Sorry rigidity is not part of the original Pascal mandate. Look at Modula and the more recent Active Oberon language, you'll see objects are not in contradiction with those goals that Niklaus had. Units neither. Generics neither. Pointer (typed) neither.

Anonymous functions (or anonymous whatever) is another debate: as i wrote previously, if you can't name it, you can't design it... Pascal is all about good design, visible in the code, readable. 90% of the time a developer reads code, usually somebody else's. This is a well-known statistic. If Pascal optimizes my reading time, I'm all for it! If the new features conform to the readability and ease-of-compiling principles, then go for it! We shouldn't dwell on the Pascal of the early 1970's. I'm fed up of seeing comparisons of 2012 C++ with 1970 Pascal...

Keep up the good work, fpc team!
Best regards,
Thierry

----- Mail original -----
De: "Arioch"
À:
Envoyé: Jeudi 30 Août 2012 10:04:08
Objet: [fpc-pascal] Re: Delphi's anonymous functions in Free Pascal

Ralf A. Quint wrote

Show quoted text 5 lines
At 12:09 AM 8/30/2012, michael.vancanneyt@ wrote: >They are IMHO a negation of what pascal stands for. If your programming +1

Well, the same should be told about everything modern pascal is.

Open and dynamic arrays, pointer math, objects, generics, even units. It was all breaking the initial Pascal strictness and rigidness.

Because what was counted "large blocks" deserving their own explicit naming back then - now seems trivial small detail.

Generics are alien to Pascal no more no less than closures.

Reply by email

Arioch
to Unknown author: +1 - anonymous functions demonstrate a laziness to software design: what you can't name…

tcoq wrote

a laziness to software design: what you can't name you actually don't design...

Guess you meant "don't want to" instead of "can't" And You mean all the non-named arrays, don't you.

"var x: array[0..10] of integer; " is not only violating Pascal Report, but also is twice lazy.
since one should name every part of design one should type like

type
    SomeEnumSemanticName = 0..10;
    SomeEnumMapSemanticName = array[SomeEnumSemanticName] of integer;
var x: SomeEnumMapSemanticName;

That has a point, for self-documenting if nothing else. But i don't believe it is practically that pervasive as your stated maxima would assume.

View this message in context: http://free-pascal-general.1045716.n5.nabble.com/Delphi-s-anonymous-functions-in-Free-Pascal-tp4911527p5711056.html Sent from the Free Pascal - General mailing list .

Reply by email

Unknown author
to Arioch: Ralf A. Quint wrote Well, the same should be told about everything modern pascal is. Open…
Arioch wrote 12 lines
Ralf A. Quint wrote > > At 12:09 AM 8/30/2012, michael.vancanneyt@ wrote: >> They are IMHO a negation of what pascal stands for. If your programming > +1 > Well, the same should be told about everything modern pascal is. Open and dynamic arrays, pointer math, objects, generics, even units. It was all breaking the initial Pascal strictness and rigidness.

Only pointer math breaks rigidness. The others do not, they enhance it.

Pascal is about readable, clearly structured, strongly typed code.

Show quoted text 5 lines
Because what was counted "large blocks" deserving their own explicit naming back then - now seems trivial small detail. Generics are alien to Pascal no more no less than closures.

Exactly. If it had been up to me, they would not have been included either.

Till now, I've seen only 1 actual use of generics in general component code, which kind of supports my theory that the only thing they are useful for is to create a list and collection kind of classes that do not need typecasts. which I think is too little justification, because that could have been achieved differently IMHO.

I started to use lambda functions in Javascript, where they are ubiquitous. Except for some trivial cases, I ended up naming them anyway, so they could be reused.

I just don't see enough justification for them, given that Pascal offers enough other structures to achieve the same effect.

Not every conceivable use case justifies a new language feature. Especially such an abomination as lambda functions, which totally destroys readability.

Michael.

Reply by email

Unknown author
to Arioch: tcoq wrote Guess you meant "don't want to" instead of "can't" And You mean all the…

No, "can't" is the correct word. In Pascal, one should have the ability to name the constructs one uses. For example, i like very much the ability to name my own Event types: "type TOnMyEvent = procedure(aStr: string) of object;". Or my Exception types. Thinking about the event name usually helps me to nail my design.

And you're right, your example is spot on. I use Pascal Analyzer (thanks Peganza!) to check my own programming (as I'm lazy as everybody else), and it detects bad design just like the example you mention. Usually because of the unnamed constant. When I have some time for refactoring, i try removing some of the more offending smells... What's nice about Pascal is that we all smell them easily... ;-)

Thierry
----- Mail original -----
De: "Arioch"
À:
Envoyé: Jeudi 30 Août 2012 10:18:31
Objet: [fpc-pascal] Re: Delphi's anonymous functions in Free Pascal

tcoq wrote

a laziness to software design: what you can't name you actually don't design...

Guess you meant "don't want to" instead of "can't" And You mean all the non-named arrays, don't you.

"var x: array[0..10] of integer; " is not only violating Pascal Report, but also is twice lazy.
since one should name every part of design one should type like

type
    SomeEnumSemanticName = 0..10;
    SomeEnumMapSemanticName = array[SomeEnumSemanticName] of integer;
var x: SomeEnumMapSemanticName;

That has a point, for self-documenting if nothing else. But i don't believe it is practically that pervasive as your stated maxima would assume.

Reply by email

Mark Morgan Lloyd
to Arioch: tcoq wrote Guess you meant "don't want to" instead of "can't" And You mean all the…
Arioch wrote 15 lines
tcoq wrote > a laziness to software design: what you can't name you actually don't > design... > Guess you meant "don't want to" instead of "can't" And You mean all the non-named arrays, don't you. "var x: array[0..10] of integer; " is not only violating Pascal Report, but also is twice lazy. since one should name every part of design one should type like type SomeEnumSemanticName = 0..10; SomeEnumMapSemanticName = array[SomeEnumSemanticName] of integer; var x: SomeEnumMapSemanticName;

Except that not defining a distinct type emphasises that the array is only being declared once, and is not being passed around as a parameter. So I'd suggest that there are cases where the first example is appropriate, except obviously that that ..10 is rarely if ever acceptable.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Arioch
to Unknown author: I beg to differ. Read Niklaus' work on why he created Pascal: two objectives stand out :…
If the new features conform to the readability

That heavily depends upon which patterns are known to reader. We all are patterns recognizers.

And today world is very different.

In my example sketch, the calling like "Data.Filter( _.TotalSale > 20 )" is concise and easy to understand.
Okay, given your heavy Pascal background you would stumble because you would see the thing between bracket as an unbelievable heresy. For people without Pascal background that would be easy to read.
At least easier than scrolling into 3 different functions probably belonging to different objects that would implement the same idea in traditional imperative way.

Generics are the ease of reading ? i saw a lot of posts calling Boost and "Modern C++ Programming" nothing else than perversion. And the enigma of generics-related compiling error messages are but a common point.

But surely remembering single TList<T> is easier than remembering dozen of specialized TLists.

It is all about scale and experience.
And we are now recognizing larger blocks of code, than in seventies. Atoms are larger today.

Can closures be abused ? Easily. Can generics be abused ? easily. Can pointers be abused? For sure.
Strings ? After i saw the tutorial(sic!) on database access, that compared word (two bytes) values via "IntToHex(value, 2) = string-constant" i am sure they easily can.

When you think about ease to read i believe you should compare to values.
* How easier would be code to read when the feature used properly ?
* How harder code would be to read when the feature is misused ?

Frankly, i don't know what weights should those values have, but i tend to believe 1st is more important. You can always make spaghetti copy-pasted code with anything.

5 lines anonymous functions are hard to debug and separate from surrounding code.
10 lines ones would be nightmare.
1-2 liners are heavily simplifying reading, where they can be applied.

and ease-of-compiling principles

Generics are one more indirection layer for compiler to care about. They are not simplifying compiling.
And they make dynamic modules like Delphi BPLs no more self-contained.

Objects are not easying compiler - now compiler should care about hidden Self parameter and generate different code for seemingly the same function, if it is method or detached function.
And i did not mentioned viortual methods and properties yet. Ref-counted interfaces are even more burden.

Dynamic arrays and strings are not easying compilation - they require a lot of hidden "compiler magic" in each statement using them.

Supporting multiple platforms, supporting multiple Pascal extensions - it all has its price making compilation more complex.

Easy compiling is good goal in the row of other ones. It has its weight but it is quite far from absolute.

-----
This is funny to remember today. ;-)
When i run BP 7 on 80286 computers, and then compared with size and speed of TP 5.5 - i was sure as hell that OOP is for lazy programmers, who cannot make code fast and small.
And i remember comparing speed of Virtual Pascal and contemporary FPC. VP bet everything on compilation efficiency. And died.

But afterall i am quitting on that. Since FPC are lacking closures i am sure here are mostly people who personally dislike them. I wanted to document why closures are good and do matter. Hopefully i did it to the extent i was able to. Surely i would not be able to convince you infinite time. So the rest of arguments would be questions of personal tastes and it would bring nothing but flamewar.

Everything is compromise, with it bright and dark sides. And everything has its personal bets in every compromise.

Allow me to congratulate you all with Lazarus 1.0 release and thank you with good and practical language implementation.

Have a nice TimeOfDay();*)

View this message in context: http://free-pascal-general.1045716.n5.nabble.com/Delphi-s-anonymous-functions-in-Free-Pascal-tp4911527p5711060.html Sent from the Free Pascal - General mailing list .

Reply by email

Lukasz Sokol
to Arioch: Ralf A. Quint wrote Well, the same should be told about everything modern pascal is. Open…
Arioch wrote 20 lines
Ralf A. Quint wrote > > At 12:09 AM 8/30/2012, michael.vancanneyt@ wrote: >> They are IMHO a negation of what pascal stands for. If your >> programming > +1 > Well, the same should be told about everything modern pascal is. Open and dynamic arrays, pointer math, objects, generics, even units. It was all breaking the initial Pascal strictness and rigidness. Because what was counted "large blocks" deserving their own explicit naming back then - now seems trivial small detail. Generics are alien to Pascal no more no less than closures.

You seem to be very rigid over your view of Pascal yourself. With everything you quoted above (but pointer math) Pascal is not a toy language any more; unfortunately many recall it as such and keep pondering about the P language...

(hey, I first had programming classes in middle school on TP6.0 when the strongest machine in computer class was a 386SX 16MHz; that the teacher had, we banged on 286...
we had some intro to (Borland) C(++) later on,
but after Pascal, C seemed so obfuscated, I gave up on it and only write small C programs for microcontrollers where it is as rigid as Pascal :J )

MvC has a point in saying 'pointer math is what spoils it' - pointer math is itself a 'feature' dragged into C++ from 'c', the verbose assembler :J

L.

Reply by email

Arioch
to Mark Morgan Lloyd: Except that not defining a distinct type emphasises that the array is only being declared…
Show quoted text 9 lines
> "var x: array[0..10] of integer; " also is twice lazy. > type > SomeEnumSemanticName = 0..10; > SomeEnumMapSemanticName = array[SomeEnumSemanticName] of integer; > var x: SomeEnumMapSemanticName; Except that not defining a distinct type emphasises that the array is only being declared once,

Same for closures, exactly.
The function is represent some primitive action or criteria that is not worth re-using and clattering namespace in both compiler and developer.

More so, i believe that holds for all named/non-named entities. Be it array, value, function of if/while condition, etc

The thing that is not named is small, with narrow use span, and is expected to be recognized and read by human as some kind of "reading atom" The thing named is more about architecture and documentation.

and is not being passed around as a parameter.

Be that the case - there would be no Open Array parameters. //well, i just want to say my opinion here. I frankly don't want arguing yet another topic //

So I'd suggest that there are cases where the first example is appropriate, except obviously that that ..10 is rarely if ever acceptable.

if 10 is unacceptable then so is 0.
one should rather explicitly name type for (0..10) rather than two constants for 0 and for 10.

View this message in context: http://free-pascal-general.1045716.n5.nabble.com/Delphi-s-anonymous-functions-in-Free-Pascal-tp4911527p5711062.html Sent from the Free Pascal - General mailing list .

Reply by email

Arioch
to Lukasz Sokol: You seem to be very rigid over your view of Pascal yourself. With everything you quoted…

Pascal never was a toy language. It always have too much required naming-and-declarations/boilerplate/obstacles/you-name-it

Basic, Logo - let them be. But not the Pascal.

It was educational language but it was damn serious educational language.

However i believe that your "but pointer math" is only a matter of habit.

Function pointers, virtual methods, interfaces - they all mean when you see function call you don't know which function is actually called.

You think of them as easing the reading only because you got used to them. You mastered those concepts and recognition patterns. Show that code to old school Classic Basic programmer, and he would flee in awe.

For a long time i sticked to Delphi 5 and did not see any benefit to upgrade, so i understand programming in classic ObjectPascal. But call me spoiled, I finally switched to XE2 and generics and closures do simplify code. But of course when and after you make them patterns you recognize at 1st glance. So, habits.

Well, finally good bye. :-)

View this message in context: http://free-pascal-general.1045716.n5.nabble.com/Delphi-s-anonymous-functions-in-Free-Pascal-tp4911527p5711063.html Sent from the Free Pascal - General mailing list .

Reply by email

Unknown author
to Arioch: That heavily depends upon which patterns are known to reader. We all are patterns…
Arioch wrote
> If the new features conform to the readability

[snip]

Show quoted text 7 lines
But afterall i am quitting on that. Since FPC are lacking closures i am sure here are mostly people who personally dislike them. I wanted to document why closures are good and do matter. Hopefully i did it to the extent i was able to. Surely i would not be able to convince you infinite time. So the rest of arguments would be questions of personal tastes and it would bring nothing but flamewar.
Regarding this: I wish to stress that my views on lambdas or closures are my own;

Other people on the compiler team may have different ideas, so maybe they will make it into the compiler. Just like Generics did, or advanced records and some other weird Delphi things of which I totally do not see the use :)

But - and I think the whole compiler team shares this idea - if implemented, it will be in a pascal-ish way, i.e. rather verbose.

Simply because it is Pascal, after all, and not some C derivative language (java, C#, Javascript, PHP, Perl whatnot...)

Michael.

Reply by email

Arioch
to Unknown author
Regarding this: I wish to stress that my views on lambdas or closures are
my own;

For what i understand, those are different things. Lambdas are runtime code generators and are out of question for natively compiled language.
Closures are not.
Maybe that is nitpicking today, since the names seems to be substituting each other outside functional languages realm where those concepts were born.

But - and I think the whole compiler team shares this idea - if

implemented,

it will be in a pascal-ish way, i.e. rather verbose.

Well, views for views.

That is Delphi way you describe. Beauty of principles. And that would be harmingly impractical.

Closures are about concise way to express one-liners. If you have to type 30 chars instead of 3 - their use became hard and impractical.

This would suppress using closures for one-liners, where that are useful, safe and enhancing code readability and composability. That would promote their use for complex code chunks where they are dangerous and bad.

From personal experience, when i first time saw how pascalish is closures

implementation in Delphi i just admired the ease in which that concept was fused into the language of very different style built upon very different ideas. It was so elegant when reading docs, i admired it. Like probably you do.

But that next to ruined their use in practice.

That is where i loose my consistency.

I do want Delphi and FPC have shared libraries, which mean i want FPC to support as much Delphi syntax as feasible.
I do want generics in both and hence want FPC support Delphi generics syntax.
I do want closures in both and... and completely cold-hearted if FP would support Delphi syntax of them or not.

While generally i feel kind of disgust at C syntax, i have to admit that their so-called lambdas are ugly but might be practical.

View this message in context: http://free-pascal-general.1045716.n5.nabble.com/Delphi-s-anonymous-functions-in-Free-Pascal-tp4911527p5711067.html Sent from the Free Pascal - General mailing list .

Reply by email

Unknown author
to Arioch
Arioch wrote 6 lines
> From personal experience, when i first time saw how pascalish is closures implementation in Delphi i just admired the ease in which that concept was fused into the language of very different style built upon very different ideas. It was so elegant when reading docs, i admired it. Like probably you do.

Not really: it breaks my eyes, just as it does in JavaScript :(

Michael.

Reply by email

Unknown author
to Arioch: Pascal never was a toy language. It always have too much required…

Thank you but I am a professional trainer for C++, Java, Ada and other languages including Lisp. I am "used to" those languages. I consistently see young professionals stumble upon those constructs they are "used to". Furthermore, all the professional users of the developed software are not "used to" and cannot read the implementation of the algorithms they have specified. This is possible and feasible in Pascal with great efficiency.

<snip>
You think of them as easing the reading only because you got used to them. You mastered those concepts and recognition patterns. Show that code to old school Classic Basic programmer, and he would flee in awe. <snip>

Reply by email

Marco van de Voort
to Unknown author: Not really: it breaks my eyes, just as it does in JavaScript :( Michael.

In our previous episode, said:

Show quoted text 7 lines
>> From personal experience, when i first time saw how pascalish is closures > implementation in Delphi i just admired the ease in which that concept was > fused into the language of very different style built upon very different > ideas. It was so elegant when reading docs, i admired it. Like probably you > do. Not really: it breaks my eyes, just as it does in JavaScript :(

This thread is mostly about the semantics and the need.

But what about the implementation? I heard that in Delphi you have to be careful with anonymous methods because it not always catches expressions and variables, and that there are many corner cases?

Reply by email

Ralf A. Quint
to Arioch: tcoq wrote Guess you meant "don't want to" instead of "can't" And You mean all the…
Arioch wrote 19 lines
tcoq wrote > > a laziness to software design: what you can't name you actually don't > design... > Guess you meant "don't want to" instead of "can't" And You mean all the non-named arrays, don't you. "var x: array[0..10] of integer; " is not only violating Pascal Report, but also is twice lazy. since one should name every part of design one should type like type SomeEnumSemanticName = 0..10; SomeEnumMapSemanticName = array[SomeEnumSemanticName] of integer; var x: SomeEnumMapSemanticName; That has a point, for self-documenting if nothing else. But i don't believe it is practically that pervasive as your stated maxima would assume.

Sorry, but that example of yours is who has
learned to program in Pascal should be able write clearly understandable programs, not obfuscate just for 'the heck of it'. But then common sense seems to have turned into a rare commodity these days.

Pascal has evolved since Wirth's original design back in the 70s, nobody is writing serious programs in the original defined language set anymore, I dare to day that even ISO Pascal is not all that useful for real life programs anymore.

A lot of extensions, like units or (objects in general) that you mentioned have been done in a way that still leave the very basics of Pascal intact.
But all the fluff that you (and others) are proposing all the time just aim at completely change the language for no other than self-serving reasons and that's why people rightfully oppose such proposals...

Ralf

Reply by email

Jorge Aldo G. de F. Junior
to Ralf A. Quint

I still fail to see where annonymous functions could succeed where functional types (part of pascal since last millenia) wouldnt...

2012/8/30 Ralf A. Quint :

Show quoted text 45 lines
At 01:18 AM 8/30/2012, Arioch wrote: > tcoq wrote > > > > a laziness to software design: what you can't name you actually don't > > design... > > > Guess you meant "don't want to" instead of "can't" > And You mean all the non-named arrays, don't you. > > "var x: array[0..10] of integer; " is not only violating Pascal Report, > but > also is twice lazy. > since one should name every part of design one should type like > > type > SomeEnumSemanticName = 0..10; > SomeEnumMapSemanticName = array[SomeEnumSemanticName] of integer; > var x: SomeEnumMapSemanticName; > > That has a point, for self-documenting if nothing else. But i don't > believe > it is practically that pervasive as your stated maxima would assume. Sorry, but that example of yours is who has learned to program in Pascal should be able write clearly understandable programs, not obfuscate just for 'the heck of it'. But then common sense seems to have turned into a rare commodity these days. Pascal has evolved since Wirth's original design back in the 70s, nobody is writing serious programs in the original defined language set anymore, I dare to day that even ISO Pascal is not all that useful for real life programs anymore. A lot of extensions, like units or (objects in general) that you mentioned have been done in a way that still leave the very basics of Pascal intact. But all the fluff that you (and others) are proposing all the time just aim at completely change the language for no other than self-serving reasons and that's why people rightfully oppose such proposals... Ralf _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

Sven Barth
to Arioch: That heavily depends upon which patterns are known to reader. We all are patterns…
Arioch wrote 6 lines
But afterall i am quitting on that. Since FPC are lacking closures i am sure here are mostly people who personally dislike them. I wanted to document why closures are good and do matter. Hopefully i did it to the extent i was able to. Surely i would not be able to convince you infinite time. So the rest of arguments would be questions of personal tastes and it would bring nothing but flamewar.

The closures (or anonymous functions as they are called in Delphi) are missing, because none of the developers has them on the important slots of the todo lists. So as long as nobody comes and implements them then they are not going to be implemented (at least in the near future). One member of the community stepped up some months ago to implement them (he even has a branch in SVN), but he didn't go far. I don't know whether it was his motivation or his time or his knowledge that left him...

Regards,
Sven

Reply by email

Jürgen Hestermann
to Ralf A. Quint: Sorry, but that example of yours is who has learned to program in Pascal should be able…
Ralf A. Quint wrote
Pascal has evolved since Wirth's original design back in the 70s

This is true. But there are two aspects of the Pascal extensions of the last years (decades) that contradict with what I would call the "spirit of Pascal":

1.) Many "extensions" add to the learning curve of newbies (where will Pascal be in 10 or 20 years and how long does it take a pupil to learn it?). Adding extensions over and over again without much thinking will ruin the language some day because nobody will try this bloated software anymore. I have programmed with Turbo Pascal quite a lot in the 80s and 90s but when I read about the "recently" added concepts I don't understand a word (and I also never missed them!). It seems that these extensions cannot even be easily explained because the concepts are very obscure and require sophisticated knowledge about the compiler to understand them. Extensions in the past were very easy to understand and to handle.

2.) Many "extensions" come from other languages and break fundamental (Pascal) laws (as I would call them). For example, to me an identifier *has* to mean the same in all contexts of a program (whether declaration, function parameter, part of an expression, ..). Dynamic arrays violate this by meaning the address of a pointer or the address of the first array element depending on whether they are dereferenced or not. Pointers should be shown as pointers and not obscured. This leads to a very lot of misunderstandings. Borland should have looked for a cleaner solution for such dynamic arrays IMO. But now the sin has been commited and cannot be withdrawn. Nevertheless, no new sins should be added anymore.

The result is that Pascal is no longer that clear and easy to learn (yet powerful) language that it was. Of course, you can still ignore all the extensions that have been added but you cannot understand foreign code anymore (which is often necessary to understand what happens in the compiler or libraries when using them).

Reply by email

Marco van de Voort
to Sven Barth: The closures (or anonymous functions as they are called in Delphi) are missing, because…

In our previous episode, Sven Barth said:

Show quoted text 8 lines
The closures (or anonymous functions as they are called in Delphi) are missing, because none of the developers has them on the important slots of the todo lists. So as long as nobody comes and implements them then they are not going to be implemented (at least in the near future). One member of the community stepped up some months ago to implement them (he even has a branch in SVN), but he didn't go far. I don't know whether it was his motivation or his time or his knowledge that left him...

Besides that, I've seen some question marks about that feature in the Delphi community too. Specially the predictability of the state that is actually captured by the anonymous function.

Reply by email

印場 乃亜
to Arioch: That heavily depends upon which patterns are known to reader. We all are patterns…

Hi,

...

Show quoted text 8 lines
----- This is funny to remember today. ;-) When i run BP 7 on 80286 computers, and then compared with size and speed of TP 5.5 - i was sure as hell that OOP is for lazy programmers, who cannot make code fast and small. And i remember comparing speed of Virtual Pascal and contemporary FPC. VP bet everything on compilation efficiency. And died.

This was sad to me. I ported the FPC system libraries (All of sysutils,pas, etc.) to VP with the goal of helping it live longer and work better on linux. The next version of SysUtils for FPC used features VPC didn't have, and I couldn't fake without modifying the compiler. I have the compiler source (The author made a "Core Team" to work on the compiler, and shared the source code and some bata builds for linux, etc.). Unfortunately, at that time I was in college, and didn't have time to learn the intricacies of i386 ASM when I was already dealing with MIPS ASM in school!

The compiler is one solid block of ASM code, and about impossible for anyone but the author to modify, I suspect. It was perhaps the right design decision at the time, however.

Show quoted text 7 lines
But afterall i am quitting on that. Since FPC are lacking closures i am sure here are mostly people who personally dislike them. I wanted to document why closures are good and do matter. Hopefully i did it to the extent i was able to. Surely i would not be able to convince you infinite time. So the rest of arguments would be questions of personal tastes and it would bring nothing but flamewar.

I don't think personal taste should come into it. As far as I know, one of the missions of FPC is to be an alternative to other Pascal compilers, which means we should strive for feature parity with the popular distributions. We could go the "Pure" route, but then we would end up with something nearly useless like GPC. (I tried GPC before around year 2000, and I couldn't even compile Hello World type programs from TP7!)

Allow me to congratulate you all with Lazarus 1.0 release and thank you with good and practical language implementation.

Likewise. I wish I had more time to contribute to this great "product".

Have a nice TimeOfDay();*)

Thank you,
Noah Silva

Show quoted text 8 lines
-- View this message in context: http://free-pascal-general.1045716.n5.nabble.com/Delphi-s-anonymous-functions-in-Free-Pascal-tp4911527p5711060.html Sent from the Free Pascal - General mailing list . _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

印場 乃亜
to Jürgen Hestermann: This is true. But there are two aspects of the Pascal extensions of the last years…

Hi,

Jürgen Hestermann wrote 7 lines
Am 2012-08-30 18:29, schrieb Ralf A. Quint: > Pascal has evolved since Wirth's original design back in the 70s This is true. But there are two aspects of the Pascal extensions of the last years (decades) that contradict with what I would call the "spirit of Pascal": 1.) Many "extensions" add to the learning curve of newbies (where will Pascal be in 10 or 20 years and how long does it take a pupil to learn it?). Adding extensions over and over again without much thinking will ruin the language some day because nobody will try this bloated software anymore. I have programmed with Turbo Pascal quite a lot in the 80s and 90s but when I read about the "recently" added concepts I don't understand a word (and I also never missed them!). It seems that these extensions cannot even be easily explained because the concepts are very obscure and require sophisticated knowledge about the compiler to understand them. Extensions in the past were very easy to understand and to handle.

Perhaps, and I agree with you to some extent. You can pick up Pascal and do something like:

program hello;
begin
  writeln('Hello World');
end;

hit compile, and watch it run - even now. And that's great, but if you want to write a web browser, or an application server, or a GUI application, you need to do an awful lot of manual work in, f.e. TP7. The first time I saw TurboVision, I thought "What a monster!", what with all those carrots for dereferencing the old style Objects, etc. Yet writing something like the TP7 editor without OOP would have been more a of a chore chan learning TurboVision for sure.

Anyone who says "I just want to save a value in a file" wouldn't want to learn SQL either - but once you have learned SQL, a lot more is possible. Actually, one of the reasons I like Pascal is because you can do low level things and high-level things in the same language. Normally I try to do everything high-level, but sometimes we have to do some dirty-work, and we can when needed. A good example is that LCL and FPC itself is written in Pascal. (Unlike, say, VB6, which is just scripting language for components written in C, really).

2.) Many "extensions" come from other languages and break fundamental (Pascal) laws (as I would call them). For example, to me an identifier *has* to mean the same in all contexts of a program (whether declaration, function parameter, part of an expression, ..). Dynamic arrays violate this by meaning the address of a pointer or the address of the first array element depending on whether they are dereferenced or not. Pointers should be shown as pointers and not obscured. This leads to a very lot of misunderstandings. Borland should have looked for a cleaner solution for such dynamic arrays IMO. But now the sin has been commited and cannot be withdrawn. Nevertheless, no new sins should be added anymore.

Well the extensions usually come because they are useful, and people have demanded them. If you are only using Pascal, then of course, they may seem like unwanted fluff. If you have used those features in other languages and then Pascal doesn't have them, then you would feel very limited. For example, pascal has "With.. Do". I use this all the time like:

With Object1 do
  begin
    size := 1;
    color := green;
    width := 84;
    Style := stNew;
  end;
In other languages I use, I have to laboriously type;
  Object1.size = 1;
  Object1.color = green;
...

But for example, ABAP programmers who have never used pascal have no idea that they are missing this feature. On the other hand, it would be super amazingly convenient if Pascal has the database integration that ABAP has, but most people who use FPC have no idea about this feature, so they don't know what they are missing.

The dynamic arrays thing also applies to LongStrings as well, but you should never have to dereference either in normal circumstances.

The result is that Pascal is no longer that clear and easy to learn (yet powerful) language that it was. Of course, you can still ignore all the extensions that have been added but you cannot understand foreign code anymore (which is often necessary to understand what happens in the compiler or libraries when using them).

Well... Understanding foreign code is difficult either way. For example, though, I think understanding foreign code that uses standard features is easier than understanding old foreign code that fakes those features with older pascal versions that lacked a standard way of implementing the functionality. For example, I have seen:

1. Hand-rolled dynamic array code full of pointer dereferences and malloc() calls.
2. Hand-rolled variant code full of structures with multiple interpretations and typecasting.
3. Hand-rolled generic features, full of typecasting random objects to "Pointer" or "PObject". (This is very common in Delphi code, since StringLists, etc., can hold "Objects").
4. Hand-rolled OOP functionality with VMT in a record.... (Before OOP was introduced into Pascal).

All of these things are easier to understand if there is a common standard that people use, even if you have to learn that standard first. For example, I don't consider myself a Java Guru, but for most basic things, there is one standard way of doing it which everyone uses, and I can look up that library to see what's going on. That's better than trying to figure out a bunch of convoluted code where the program logic is intermixed with the implementation of features that should be in the compiler or (at least) a separate library).

Either way, when you want to do complicated things, you will need to choose between three options
1. Implement the feature manually in code (if possible)
2. Do without the feature and write your program (if possible, may require much more effort)
3. Have the feature implemented into the language, so that everyone can use it, and use it in the same way.

If you are only writing simple programs, though, you can of course ignore the extensions in most cases. I personally ignore a lot of things. I very rarely use Variants, TStream, etc. I also prefer to write and execute SQL statements than to use the OOP database features. On the other hand, some new features I used immediately as they became available because they allow me to do that much less work or stop using TypeCasting (Dynamic Arrays, Long Strings, Generics, etc.)

At any rate, it really comes down to what people want FPC to be:
1. A viable alternative to Delphi and the other compilers and an active language for developers to use.
2. A project to duplicate the antique TP7 compiler on modern hardware for enthusiast programmers.

I am not saying that option 2 is bad, but I think there is a lot of demand for option #1. Personally, if I couldn't do #1 in Pascal, I would be forced to use Java or Mono for writing complex cross-platform software, so I hope FPC keeps on track.

Thank you,
Noah Silva

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

Reply by email