Re: [fpc-pascal] "Is nested" vs "of object" compatibility with global functions

2022-05-28 Thread Michael Van Canneyt via fpc-pascal



On Sun, 29 May 2022, Hairy Pixels via fpc-pascal wrote:


I’ve been testing out all the different function pointer types in FPC to
test their compatibility with each other and I noticed that “is nested”
can accept a global function declaration but “of object” can not.  What is
the reason for this exactly?  I wouldn’t expect nested function types to
accept global functions but since they do I wonder why “of object” is
different.


Because you're pushing a parameter which does not exist in the case of a
global function.



I think they both have a hidden first parameter (like self) and nested
types simply ignore this for global functions so I would think objects
types could do the same.


I cannot comment on the 'is nested', I don't know what the extra field is
for. I assume a parent stack frame pointer, which can perfectly be nil,
presumably.

A method pointer is actually 2 fields, both pointers: 
the data (self) and the address (location of method).


Because you cannot distinguish between 'self = nil' and 'there is no self'
when actually calling the method, it's not possible to assign a global method: 
you would be pushing a 'self' parameter to a procedure that is not expecting a

'self' parameter, wreaking havoc on the stack.

Theoretically one could add a third field, or maybe encode a special
value to distinguish between the two, but then you would need to add 
some logic at every call of an 'of object' method to determine what is needed. 
That would slow things down, and would be not be Delphi compatible.
There is plenty of code out there that assumes the current mechanism to 
'just work'


Similarly, you could let all global methods accept a 'self' pointer which is
simply Nil, but same argument applies: it slows things down (extra parameter to
handle) and is not TP nor Delphi compatible.

When starting from zero, one could probably make all 3 methods (plain
procedure, 'of object' and 'is nested' compatible - maybe even 
'reference to', but for historical reasons it is not possible.


Michael.___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


[fpc-pascal] "Is nested" vs "of object" compatibility with global functions

2022-05-28 Thread Hairy Pixels via fpc-pascal
I’ve been testing out all the different function pointer types in FPC to test 
their compatibility with each other and I noticed that “is nested” can accept a 
global function declaration but “of object” can not. What is the reason for 
this exactly? I wouldn’t expect nested function types to accept global 
functions but since they do I wonder why “of object” is different.

I think they both have a hidden first parameter (like self) and nested types 
simply ignore this for global functions so I would think objects types could do 
the same.

Regards,
Ryan Joseph

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Feature Announcement: Function References and Anonymous Functions

2022-05-28 Thread Thomas Kurz via fpc-pascal
This is horrendous code, especially the last example. Looks like PHP or 
JavaScript, which I hate because their code is hard to read. I'm using pascal 
because I like its clean and easy-to-read syntax.

"-1" is a statement that should give a compiler error. "Result" and "Exit(x)" 
are established constructs and I don't see any need for changing, or even 
worse: omitting, them.

What should the data type of "left, right" be?

What should "@" mean?



- Original Message - 
From: Benito van der Zander via fpc-pascal 
To: fpc-pascal@lists.freepascal.org 
Sent: Saturday, May 28, 2022, 14:04:46
Subject: [fpc-pascal] Feature Announcement: Function References and Anonymous 
Functions

Hi,

> Sort((left, right) begin
>  if left < right then
>result := -1
>  else if left > right then
>result := 1
>  else
>result := 0;
>end);

One could introduce the @ operator to get a reference to a block of code.

Sort( @(left, right) begin
 if left < right then
   result := -1
 else if left > right then
   result := 1
 else
   result := 0;
   end);


The "result" variable is also ugly. You could make "if" an expression:

Sort( @(left, right) begin
 result :=
   if left < right then -1
   else if left > right then 1
   else 0;
   end);


Then the begin end could be removed too. Make @:= an operator to turn an 
expression to a function

Sort( @(left, right) :=
if left < right then -1
else if left > right then 1
else 0;
   );





Benito

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Feature Announcement: Function References and Anonymous Functions

2022-05-28 Thread Hairy Pixels via fpc-pascal


> On May 27, 2022, at 6:31 PM, Marco van de Voort via fpc-pascal 
>  wrote:
> 
> Ditto! https://gitlab.com/freepascal.org/lazarus/lazarus/-/issues/39774
> 
> This ticket also contains an experimental patch for anonymous method queue 
> and synchronize. (required to reproduce)

Yeah code tools is basically broken right now. I don’t think I can even use it 
right now from my language server because I get the error: invalid mode switch 
“functionreferences”. Hopefully this can be fixed soon.

Regards,
Ryan Joseph

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Feature Announcement: Function References and Anonymous Functions

2022-05-28 Thread Hairy Pixels via fpc-pascal


> On May 28, 2022, at 7:04 PM, Benito van der Zander via fpc-pascal 
>  wrote:
> 
> The "result" variable is also ugly. You could make "if" an expression:
> 
> Sort( @(left, right) begin
> result :=  
>   if left < right then -1
>   else if left > right then 1
>   else 0;
>   end);

Swift, C# and JavaScript etc…  allow you to omit the return statement if the 
function body is a single expression. I don’t think any languages I’m aware of 
break the rules of expression though like this is proposing but you could use 
exit() and it would look a little better.

> 
> 
> 
> Then the begin end could be removed too. Make @:= an operator to turn an 
> expression to a function
> 
> Sort( @(left, right) := 
>if left < right then -1
>else if left > right then 1
>else 0;
>   );

I don’t think you need the @ operator here since the ():= is enough to denote a 
function. This is like the “arrow” syntax in JavaScript and it makes sense to 
me. It’s a good idea I think.

Come to think of it is FPC going to support capture lists? Right now the entire 
scope is captured but this is not always ideal. Right now there’s no syntax 
currently available that would support that.


Regards,
Ryan Joseph

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Feature Announcement: Function References and Anonymous Functions

2022-05-28 Thread Hairy Pixels via fpc-pascal


> On May 28, 2022, at 6:39 PM, Michael Van Canneyt via fpc-pascal 
>  wrote:
> 
> And I'm sure it finds these very understandable (live examples):
> 
> [s: string]: ((s: string, cb: (done: any) => void) => void) & ((cb: (done: 
> any) => void) => void) & {only: any, skip: any};
> load: (url: string, onLoad: (object3D: THREE.Object3D) => void, onProgress?: 
> (progress: ProgressEvent) => void, onError?: (event: ErrorEvent) => void) => 
> void;
> function comp(c: (c: C) => D, b: (b: B) => C, a: (a: A) => B): 
> (a: A) => D;
> function comp(d: (d: D) => E, c: (c: C) => D, b: (b: B) => C, 
> a: (a: A) => B): (a: A) => E;
> singleton = _.memoize((classInstance: new () => T) => new classInstance());
> function cacheGetter(judgeFunc: () => boolean, returnCacheValueFunc: () => 
> any, setCacheFunc: (returnVal: any) => void): (target: any, name: any, 
> descriptor: any) => any;
> 

Yes I see your point here but this can happen to any language with closures and 
is something FPC needs to reckon with now. Having verbose function declarations 
could make these kind of nested closures even worse than this.

I’m not up to date on how languages like JavaScript are dealing with this 
problem in their inherently concurrent code but I think they’re moving away 
from callbacks and closures. See http://callbackhell.com.

My point has to do with the best case scenario where adding a function which 
mean the user needs to scroll up dozens of lines to see what the function does 
even though it may be only a single expression. This is very common for filter, 
map etc… container functions. Adding in a fat function declaration doesn’t help 
the programmer since they already know what the TList.Filter function does and 
the extra lines make it hard to see what the actual code does.

For example you want to filter out items from a list with a value of less than 
10. The function is only a single expression so wrapping it up in a 3 extra 
lines of code is just obscuring the code in my opinion.

Swift even has a convention for if the last parameter is a function you can 
call it with something like this:

list.Filter begin
  result := $0 < 10;
  end;

I really don’t see how the extra "function (item: integer): boolean” makes that 
easier to read or adds more information. Maybe if you started doing stupid 
nesting things it will make a difference?

list.Filter begin
  result := $0.PeformCheck begin
   result := $0 < 10;
 end;
end;



list.Filter(function (item: integer): boolean
begin
  result := item.PeformCheck(function: boolean
 begin
   result := self < 10;
 end);
end);

They both look not great to me but I think this is more with the nesting aspect 
than the function declaration.

What about plain procedures with no parameters? 

timer.Finished(procedure
   begin
 DoTheNextThing;
   end);

Or this:

timer.Finished(procedure begin DoTheNextThing end);

I’m just not seeing how it helps to write in the procedure keyword in these 
cases.

Anyways, it’s too early to know how this is going to work and I don’t do much 
concurrent code in Pascal so I likely won’t ever have a chance to write deeply 
nested functions but lets see what other people end of doing and how it looks.


Regards,
Ryan Joseph

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Compiler flag define or $IFOPT for optimizations

2022-05-28 Thread Tomas Hajny via fpc-pascal

On 2022-05-28 13:44, Benito van der Zander via fpc-pascal wrote:


Hi,


I want to show how my program was compiled.

Now I have string like "FPC3.2.2 i386-Linux R+C+" from

  compiler := 'FPC' + {$INCLUDE %FPCVERSION%} + ' ' + {$INCLUDE
%FPCTargetCPU%}+'-'+{$INCLUDE %FPCTargetOS%}+ ' ' + {$IfOpt
R+}+'R+'{$endif} {$IfOpt S+}+'S+'{$endif} {$IfOpt O+}+'O+'{$endif}
{$IfOpt Q+}+'Q+'{$endif} {$IfOpt M+}+'M+'{$endif} {$IfOpt
C+}+'C+'{$endif};

But the optimization level (-O2 or -O1 ...) is missing.

Is there an IFOPT for that? Or a define with all the arguments


I don't think that there's such an option at the moment. However, you 
can possibly solve it by always taking the options from an environment 
variable to the command line and then including contents of this command 
line to your sources. I don't think that it makes much sense for the 
compiler to provide such an option, because unlike the compiler version, 
different options (including the optimization level) may be used for 
compilation of different units and there's no such a thing as a general 
optimization level valid for the complete compiled program from the 
compiler point of view. You can introduce something like that yourself 
by always building all your sources from scratch, but then the solution 
outlined above should work for you.


Tomas
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Feature Announcement: Function References and Anonymous Functions

2022-05-28 Thread Benito van der Zander via fpc-pascal

Hi,


Sort((left, right) begin
 if left < right then
   result := -1
 else if left > right then
   result := 1
 else
   result := 0;
   end);


One could introduce the @ operator to get a reference to a block of code.

Sort( @(left, right) begin
if left < right then
  result := -1
else if left > right then
  result := 1
else
  result := 0;
  end);


The "result" variable is also ugly. You could make "if" an expression:

Sort( @(left, right) begin
result :=
  if left < right then -1
  else if left > right then 1
  else 0;
  end);


Then the begin end could be removed too. Make @:= an operator to turn an 
expression to a function


Sort( @(left, right) :=
   if left < right then -1
   else if left > right then 1
   else 0;
  );





Benito
On 28.05.22 08:47, Hairy Pixels via fpc-pascal wrote:

I’ve had some time to play with this now and my first piece of feedback is that 
given my experience with other languages, the most common usage of closures is 
by passing them as arguments to functions.

Compared to the other languages I’m using now I’d say that we should be 
inferring more of the context of the receiving function type and not requiring 
the programmer to type out the full function header as in the example below 
(especially in the case there are no local variables declared).

Sort(function(left, right: Double): integer
   begin
 if left < right then
   result := -1
 else if left > right then
   result := 1
 else
   result := 0;
   end);

It’s hard to say what the best policy is for Pascal but some combination of the 
function/procedure keyword, parameter type names and return type could be 
omitted or shortened in various ways.

Given we know the function type from the parameter list we could infer most of 
the information and provide a more limited set of syntax, for example like this 
(Swift like):

Sort((left, right) begin
 if left < right then
   result := -1
 else if left > right then
   result := 1
 else
   result := 0;
   end);

There is even the most limited shorthand (from Swift again) which uses token to 
represent the arguments as they are ordered.

Sort(begin
   if $0 < right then
 result := -1
   else if $0 > $1 then
 result := 1
   else
 result := 0;
 end);

Regards,
Ryan Joseph

___
fpc-pascal maillist  -fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


[fpc-pascal] Compiler flag define or $IFOPT for optimizations

2022-05-28 Thread Benito van der Zander via fpc-pascal

Hallo,


I want to show how my program was compiled.

Now I have string like "FPC3.2.2 i386-Linux R+C+" from


  compiler := 'FPC' + {$INCLUDE %FPCVERSION%} + ' ' + {$INCLUDE 
%FPCTargetCPU%}+'-'+{$INCLUDE %FPCTargetOS%}+ ' ' + {$IfOpt 
R+}+'R+'{$endif} {$IfOpt S+}+'S+'{$endif} {$IfOpt O+}+'O+'{$endif} 
{$IfOpt Q+}+'Q+'{$endif} {$IfOpt M+}+'M+'{$endif} {$IfOpt C+}+'C+'{$endif};


But the optimization level (-O2 or -O1 ...) is missing.

Is there an IFOPT for that? Or a define with all the arguments


Bye,

Benito

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Feature Announcement: Function References and Anonymous Functions

2022-05-28 Thread Michael Van Canneyt via fpc-pascal



On Sat, 28 May 2022, Hairy Pixels via fpc-pascal wrote:





On May 28, 2022, at 2:06 PM, Michael Van Canneyt via fpc-pascal 
 wrote:

Ah...

The desire to make a programming language terse and unreadable as a consequence.
If you want that, use C#, Javascript or one of the ubiquitous languages for 
bracket fetishists.
Scala & Rust top the bill in terms of unreadability.

So no, that's a "No pasarán".


Well that’s been my experience using both Swift and C# frequently over the
last couple years that you don’t actually need to see the full function
declaration in most instances because it’s inferred from the context.


I'm happy for the computer that it can infer things from the context in
milliseconds. Really, I stand in awe...

And I'm sure it finds these very understandable (live examples):

[s: string]: ((s: string, cb: (done: any) => void) => void) & ((cb: (done: any) => 
void) => void) & {only: any, skip: any};
load: (url: string, onLoad: (object3D: THREE.Object3D) => void, onProgress?: (progress: 
ProgressEvent) => void, onError?: (event: ErrorEvent) => void) => void;
function comp(c: (c: C) => D, b: (b: B) => C, a: (a: A) => B): (a: A) 
=> D;
function comp(d: (d: D) => E, c: (c: C) => D, b: (b: B) => C, a: (a: 
A) => B): (a: A) => E;
singleton = _.memoize((classInstance: new () => T) => new classInstance());
function cacheGetter(judgeFunc: () => boolean, returnCacheValueFunc: () => any, 
setCacheFunc: (returnVal: any) => void): (target: any, name: any, descriptor: any) => 
any;

However, I as a human have a brain that works at lower clock cycles, but even so 
I like to see at a glance what is intended without having to think too long on 
'what on earth could missus X have meant here ?'.


That means providing a little more context/structure, and keeping the door
firmly closed for syntax that allows absurd monstrosities as the things above. 
(and preferably lock it, take out the key and throw it away while we're at it)


This is - incidentally - also why I think pascal should never allow type 
definitions
in function arguments.

For similar reasons I deplore the popularity of YAML or markdown, which all
too often provide too little structure to grasp what is meant. 
By contrast XML is too much cruft, but e.g. JSON strikes a good balance.


Programming languages are meant for humans, not for computers.

If it were up to the computer, we'd probably simply write out programs as 
sequences
of 0-s and 1-s. Guaranteed to be the shortest notation, but good luck trying
to make sense of that as a human. I suspect punched cards are a thing of the 
past
just for this reason.

The downside is that every human has his likes and dislikes.

But, if you actually prefer the above syntax to the more verbose pascal, you're in luck: 
There are many languages that will allow you to knock yourself out =-)


Michael.___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Feature Announcement: Function References and Anonymous Functions

2022-05-28 Thread Hairy Pixels via fpc-pascal


> On May 28, 2022, at 2:06 PM, Michael Van Canneyt via fpc-pascal 
>  wrote:
> 
> Ah...
> 
> The desire to make a programming language terse and unreadable as a 
> consequence.
> If you want that, use C#, Javascript or one of the ubiquitous languages for 
> bracket fetishists.
> Scala & Rust top the bill in terms of unreadability.
> 
> So no, that's a "No pasarán".

Well that’s been my experience using both Swift and C# frequently over the last 
couple years that you don’t actually need to see the full function declaration 
in most instances because it’s inferred from the context. I’m actually finding 
it harder to read the Pascal syntax because there’s so much slammed in the 
function call.

Regards,
Ryan Joseph

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Feature Announcement: Function References and Anonymous Functions

2022-05-28 Thread Michael Van Canneyt via fpc-pascal



On Sat, 28 May 2022, Hairy Pixels via fpc-pascal wrote:


I’ve had some time to play with this now and my first piece of feedback is that 
given my experience with other languages, the most common usage of closures is 
by passing them as arguments to functions.

Compared to the other languages I’m using now I’d say that we should be 
inferring more of the context of the receiving function type and not requiring 
the programmer to type out the full function header as in the example below 
(especially in the case there are no local variables declared).

Sort(function(left, right: Double): integer
 begin
   if left < right then
 result := -1
   else if left > right then
 result := 1
   else
 result := 0;
 end);

It’s hard to say what the best policy is for Pascal but some combination of the 
function/procedure keyword, parameter type names and return type could be 
omitted or shortened in various ways.


Ah...

The desire to make a programming language terse and unreadable as a consequence.
If you want that, use C#, Javascript or one of the ubiquitous languages for 
bracket fetishists.
Scala & Rust top the bill in terms of unreadability.

So no, that's a "No pasarán".

Pascal is verbose and explicit, it enhances readability & clarity of code. 
Any proposal to undo that, is not acceptable.


If it was not for Delphi compatibility, I would kick out anonymous functions
outright. Local functions can fulfill the need for closures perfectly,
which results in more readable code as far as I am concerned.

Michael.___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Feature Announcement: Function References and Anonymous Functions

2022-05-28 Thread Hairy Pixels via fpc-pascal
I’ve had some time to play with this now and my first piece of feedback is that 
given my experience with other languages, the most common usage of closures is 
by passing them as arguments to functions.

Compared to the other languages I’m using now I’d say that we should be 
inferring more of the context of the receiving function type and not requiring 
the programmer to type out the full function header as in the example below 
(especially in the case there are no local variables declared).

Sort(function(left, right: Double): integer
  begin
if left < right then
  result := -1
else if left > right then
  result := 1
else
  result := 0;
  end);

It’s hard to say what the best policy is for Pascal but some combination of the 
function/procedure keyword, parameter type names and return type could be 
omitted or shortened in various ways. 

Given we know the function type from the parameter list we could infer most of 
the information and provide a more limited set of syntax, for example like this 
(Swift like):

Sort((left, right) begin
if left < right then
  result := -1
else if left > right then
  result := 1
else
  result := 0;
  end);

There is even the most limited shorthand (from Swift again) which uses token to 
represent the arguments as they are ordered.

Sort(begin
  if $0 < right then
result := -1
  else if $0 > $1 then
result := 1
  else
result := 0;
end);

Regards,
Ryan Joseph

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal