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

2022-05-30 Thread Bart via fpc-pascal
On Mon, May 30, 2022 at 7:25 AM Sven Barth via fpc-pascal
 wrote:

> === code begin ===
>
> Sort(lamba (left, right) as
>   if left < right then -1
>   else if left > right then 1
>   else 0);
>

This doesn't look like Pascal at all.
I definitively hope this is not the future of our beautiful language.

-- 
Bart
___
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-29 Thread Sven Barth via fpc-pascal

Am 28.05.2022 um 14:04 schrieb 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 sequence "@(identifier" is already a valid sequence (because 
"@(SomeVar)" is valid) and I'm definitely and absolutely against 
introducing another ambigous syntax as I already have enough headaches 
with Delphi's generic syntax.




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);


Allowing if (and case) to be an expression, too, is something I'm still 
toying with independantly of this...




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 personally would have a bit more verbose syntax though it would have 
the same problem regarding type inference which would be an absolute 
PITA to implement (not to mention the opposition from the other core devs):


=== code begin ===

Sort(lamba (left, right) as
  if left < right then -1
  else if left > right then 1
  else 0);

=== code end ===

Regards,
Sven___
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] 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


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


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

2022-05-27 Thread Ondrej Pokorny via fpc-pascal

On 27.05.2022 00:23, Zoë Peterson via fpc-pascal wrote:

Sven,

I'm absolutely thrilled to see this finally merged.  I sincerely 
appreciate all of the work that you and Blaise put into it over such a 
long time.  I can't wait to see what the community is able to do with 
it.  Thank you, and thank you to the entire Free Pascal team for 
everything you've all built.


Sven & Blaise,

I thank you for this enormous achievement as well!

Ondrej

___
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-27 Thread Marco van de Voort via fpc-pascal


On 27-5-2022 14:12, Sven Barth via fpc-pascal wrote:

You couldn't have written a test that's independent of TThread? 梁
When I saw no reactions on core this morning, I dumped everything I had 
to the respective issue trackers. I'm not sure if I can get all of this 
reproduced on my private laptop when I'm away this weekend.


If it is about the overload case: well, you said it would be easy 
because objfpc already did it right :-)


___
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-27 Thread Sven Barth via fpc-pascal
Marco van de Voort via fpc-pascal  schrieb
am Fr., 27. Mai 2022, 13:31:

>
> On 27-5-2022 00:46, Mattias Gaertner via fpc-pascal wrote:
> >
> >> As these two features are rather complicated there might still be a
> >> huge bundle of bugs lurking around so I ask you to test them to year
> >> heart's content and report found bugs
> > First!
>
> 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)
>

You couldn't have written a test that's independent of TThread? 梁

Regards,
Sven

>
___
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-27 Thread Marco van de Voort via fpc-pascal



On 27-5-2022 00:46, Mattias Gaertner via fpc-pascal wrote:



As these two features are rather complicated there might still be a
huge bundle of bugs lurking around so I ask you to test them to year
heart's content and report found bugs

First!


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)

___
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-26 Thread Sven Barth via fpc-pascal

Am 27.05.2022 um 00:46 schrieb Mattias Gaertner via fpc-pascal:

On Thu, 26 May 2022 21:47:06 +0200
Sven Barth via fpc-pascal  wrote:

As these two features are rather complicated there might still be a
huge bundle of bugs lurking around so I ask you to test them to year
heart's content and report found bugs

First!

At least it was an easy one for starters ^^'

Regards,
Sven
___
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-26 Thread Hairy Pixels via fpc-pascal


> On May 27, 2022, at 2:47 AM, Sven Barth via fpc-pascal 
>  wrote:
> 
> Further RTL enhancements like the declaration of TProc<> or the addition of a 
> TThread.Queue() that takes a function reference will come in the near future 
> now that the basics on the compiler side are done. Maybe we can now also 
> tackle ports of libraries like Spring4D and OmniThreadLibrary. There's also 
> the idea to introduce a syntax to control whether symbols are captured 
> by-reference (as currently) or by-value.
> 
> Enjoy!

Huge news, I’m so excited about this. Thank you both.

As discussed over the last years, now that we’ve implemented the anonymous 
functions part can we consider an optimization for closures that don’t leave 
the current scope? I explored the possibility of using the existing nested 
function feature and I think that would work great with the anonymous functions 
syntax.

The open questions are:

1) How does the compiler know the closure will not leave the scope?
2) The actual implementation, leverage the nested functions which are stacked 
based objects or change the closure capture object to be a record instead of an 
interface (much more work I believe).

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-26 Thread Thomas Kurz via fpc-pascal
Great!!! Thank you very very much :)))


- Original Message - 
From: Sven Barth via fpc-pascal 
To: fpc-annou...@lists.freepascal.org 
Sent: Thursday, May 26, 2022, 21:47:06
Subject: [fpc-pascal] Feature Announcement: Function References and Anonymous 
Functions

Dear Free Pascal Community,

The Free Pascal Developer team is pleased to finally announce the 
addition of a long awaited feature, though to be precise it's two 
different, but very much related features: Function References and 
Anonymous Functions. These two features can be used independantly of 
each other, but their greatest power they unfold when used together.

These features are based on the work by Blaise.ru, so thank you very 
much and I hope you're doing well considering the current situation.

In the following we'll highlight both features separately and then we'll 
take a look at using them together.

= Function References =

Function References (also applicable names are Procedure References and 
Routine References, in the following only Function References will be 
used) are types that can take a function (or procedure or routine), 
method, function variable (or procedure variable or routine variable), 
method variable, nested function (or nested procedure or nested routine) 
or an anonymous function (or anonymous procedure or anonymous routine) 
as a value. The function reference can then be used to call the provided 
function just like other similar routine pointer types. In contrast to 
these other types nearly all function-like constructs can be assigned to 
it (the only exception are nested function variables (or nested 
procedure variables or nested routine variables), more about that later 
on) and then used or stored.

Function references are enabled with the modeswitch FUNCTIONREFERENCES 
(the following examples will assume that this modeswitch is provided).

A function reference is declared as follows:

REFERENCE TO FUNCTION|PROCEDURE [(argumentlist)][: resulttype;] 
[directives;]

Examples:

=== code begin ===

type
   TProcLongInt = reference to procedure(aArg: LongInt); stdcall;
   TFuncTObject = reference to function(aArg: TObject): TObject;

=== code end ===

Like other function pointer types function references can also be 
declared as generic:

=== code begin ===

type
   generic TGenericProc = reference to procedure(aArg: T);

=== code end ===

As you can see, once function references are enabled you can't use the 
identifier "REFERENCE" as part of an alias declaration without using "&":

=== code begin ===

type
   someref = reference; // will fail
   someref =  // correct fix

var
   somevar: reference; // will fail
   somevar:  // correct fix

=== code end ===

A function reference variable can then be called like any other function 
pointer type:

=== code begin ===

var
   p: TProcLongInt;
begin
   p := @SomeLongIntProc;
   p(42);
end.

=== code end ===

If a function reference has no parameters then you need to use "()" 
nevertheless in the FPC/ObjFPC modes like for other function pointer types:

=== code begin ===

type
   TProc = reference to procedure;
var
   p: TProc;
begin
   p := @SomeProcedure;
   p(); // required
   p; // this can be used e.g. in mode Delphi
end.

=== code end ===

Like other function pointer types they can also be declared anonymously 
as part of a variable, field declaration (but not as part of a paramater 
declaration):

=== code begin ===

var
   f: reference to function: LongInt;

type
   TTest = class
 f: reference to procedure;
   end;

=== code end ===

They get their great power from a point that is for once *not* 
considered an implementation detail: function references are in fact 
internally declared as reference counted interfaces with a single 
Invoke() method of the provided signature. So the above examples are in 
fact declared like this:

=== code begin ===

type
   TProcLongInt = interface(IInterface)
 procedure Invoke(aArg: LongInt); stdcall; overload;
   end;

   TFuncTObject = interface(IInterface)
 procedure Invoke(aArg: TObject): TObject; overload;
   end;

   generic TGenericProc = interface(IInterface)
 procedure Invoke(aArg: T); overload;
   end;

=== code end ===

This has a few implications:
- in the RTTI this will appear like a normal interface
- it reacts to the $M directive like a normal interface
- it is a managed type
- it has *no* valid GUID
- it can be implemented by a class
- it can be inherited from

Especially the last two points are important.

That the interface can be implemented means that much more functionality 
and state can be added to a function reference:

=== code begin ===

type
   TFunc = reference to function: LongInt;

   TSomeImpl = class(TInterfacedObject, TFunc)
 f: LongInt;
 function Invoke: LongInt;
   end;

function TSomeImpl.Invoke: LongInt;
begin
   Result := f;
end;

var
   t: TSomeImpl;
   f: TFunc;
begin
   t := TSomeImpl.Create;
   f := t;
   Writeln(

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

2022-05-26 Thread Mattias Gaertner via fpc-pascal
On Thu, 26 May 2022 21:47:06 +0200
Sven Barth via fpc-pascal  wrote:

>[...]
> The Free Pascal Developer team is pleased to finally announce the 
> addition of a long awaited feature, though to be precise it's two 
> different, but very much related features: Function References and 
> Anonymous Functions.

\O/


>[...]

> As these two features are rather complicated there might still be a
> huge bundle of bugs lurking around so I ask you to test them to year
> heart's content and report found bugs

First!

>[...]

Mattias
___
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-26 Thread Zoë Peterson via fpc-pascal

Sven,

I'm absolutely thrilled to see this finally merged.  I sincerely 
appreciate all of the work that you and Blaise put into it over such a 
long time.  I can't wait to see what the community is able to do with 
it.  Thank you, and thank you to the entire Free Pascal team for 
everything you've all built.


--
Zoë Peterson
Scooter Software


___
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-26 Thread Michael Van Canneyt via fpc-pascal


Hello !

Nice job, kudos both for Blaise and Sven, and special thanks to 
Zoë Peterson for donating the code to FPC, as Scooter Software sponsored

the initial work by Blaise.

I'm glad to see that the FPC implementation makes the distinction between
function references and anonymous functions very explicitly :-)

Michael.

On Thu, 26 May 2022, Sven Barth via fpc-pascal wrote:


Dear Free Pascal Community,

The Free Pascal Developer team is pleased to finally announce the 
addition of a long awaited feature, though to be precise it's two 
different, but very much related features: Function References and 
Anonymous Functions. These two features can be used independantly of 
each other, but their greatest power they unfold when used together.


These features are based on the work by Blaise.ru, so thank you very 
much and I hope you're doing well considering the current situation.


In the following we'll highlight both features separately and then we'll 
take a look at using them together.


= Function References =

Function References (also applicable names are Procedure References and 
Routine References, in the following only Function References will be 
used) are types that can take a function (or procedure or routine), 
method, function variable (or procedure variable or routine variable), 
method variable, nested function (or nested procedure or nested routine) 
or an anonymous function (or anonymous procedure or anonymous routine) 
as a value. The function reference can then be used to call the provided 
function just like other similar routine pointer types. In contrast to 
these other types nearly all function-like constructs can be assigned to 
it (the only exception are nested function variables (or nested 
procedure variables or nested routine variables), more about that later 
on) and then used or stored.


Function references are enabled with the modeswitch FUNCTIONREFERENCES 
(the following examples will assume that this modeswitch is provided).


A function reference is declared as follows:

REFERENCE TO FUNCTION|PROCEDURE [(argumentlist)][: resulttype;] 
[directives;]


Examples:

=== code begin ===

type
  TProcLongInt = reference to procedure(aArg: LongInt); stdcall;
  TFuncTObject = reference to function(aArg: TObject): TObject;

=== code end ===

Like other function pointer types function references can also be 
declared as generic:


=== code begin ===

type
  generic TGenericProc = reference to procedure(aArg: T);

=== code end ===

As you can see, once function references are enabled you can't use the 
identifier "REFERENCE" as part of an alias declaration without using "&":


=== code begin ===

type
  someref = reference; // will fail
  someref =  // correct fix

var
  somevar: reference; // will fail
  somevar:  // correct fix

=== code end ===

A function reference variable can then be called like any other function 
pointer type:


=== code begin ===

var
  p: TProcLongInt;
begin
  p := @SomeLongIntProc;
  p(42);
end.

=== code end ===

If a function reference has no parameters then you need to use "()" 
nevertheless in the FPC/ObjFPC modes like for other function pointer types:


=== code begin ===

type
  TProc = reference to procedure;
var
  p: TProc;
begin
  p := @SomeProcedure;
  p(); // required
  p; // this can be used e.g. in mode Delphi
end.

=== code end ===

Like other function pointer types they can also be declared anonymously 
as part of a variable, field declaration (but not as part of a paramater 
declaration):


=== code begin ===

var
  f: reference to function: LongInt;

type
  TTest = class
    f: reference to procedure;
  end;

=== code end ===

They get their great power from a point that is for once *not* 
considered an implementation detail: function references are in fact 
internally declared as reference counted interfaces with a single 
Invoke() method of the provided signature. So the above examples are in 
fact declared like this:


=== code begin ===

type
  TProcLongInt = interface(IInterface)
    procedure Invoke(aArg: LongInt); stdcall; overload;
  end;

  TFuncTObject = interface(IInterface)
    procedure Invoke(aArg: TObject): TObject; overload;
  end;

  generic TGenericProc = interface(IInterface)
    procedure Invoke(aArg: T); overload;
  end;

=== code end ===

This has a few implications:
- in the RTTI this will appear like a normal interface
- it reacts to the $M directive like a normal interface
- it is a managed type
- it has *no* valid GUID
- it can be implemented by a class
- it can be inherited from

Especially the last two points are important.

That the interface can be implemented means that much more functionality 
and state can be added to a function reference:


=== code begin ===

type
  TFunc = reference to function: LongInt;

  TSomeImpl = class(TInterfacedObject, TFunc)
    f: LongInt;
    function Invoke: LongInt;
  end;

function TSomeImpl.Invoke: LongInt;
begin
  Result := f;
end;

var
  t: TSomeImpl;
  f: TFunc;

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

2022-05-26 Thread Sven Barth via fpc-pascal

Dear Free Pascal Community,

The Free Pascal Developer team is pleased to finally announce the 
addition of a long awaited feature, though to be precise it's two 
different, but very much related features: Function References and 
Anonymous Functions. These two features can be used independantly of 
each other, but their greatest power they unfold when used together.


These features are based on the work by Blaise.ru, so thank you very 
much and I hope you're doing well considering the current situation.


In the following we'll highlight both features separately and then we'll 
take a look at using them together.


= Function References =

Function References (also applicable names are Procedure References and 
Routine References, in the following only Function References will be 
used) are types that can take a function (or procedure or routine), 
method, function variable (or procedure variable or routine variable), 
method variable, nested function (or nested procedure or nested routine) 
or an anonymous function (or anonymous procedure or anonymous routine) 
as a value. The function reference can then be used to call the provided 
function just like other similar routine pointer types. In contrast to 
these other types nearly all function-like constructs can be assigned to 
it (the only exception are nested function variables (or nested 
procedure variables or nested routine variables), more about that later 
on) and then used or stored.


Function references are enabled with the modeswitch FUNCTIONREFERENCES 
(the following examples will assume that this modeswitch is provided).


A function reference is declared as follows:

REFERENCE TO FUNCTION|PROCEDURE [(argumentlist)][: resulttype;] 
[directives;]


Examples:

=== code begin ===

type
  TProcLongInt = reference to procedure(aArg: LongInt); stdcall;
  TFuncTObject = reference to function(aArg: TObject): TObject;

=== code end ===

Like other function pointer types function references can also be 
declared as generic:


=== code begin ===

type
  generic TGenericProc = reference to procedure(aArg: T);

=== code end ===

As you can see, once function references are enabled you can't use the 
identifier "REFERENCE" as part of an alias declaration without using "&":


=== code begin ===

type
  someref = reference; // will fail
  someref =  // correct fix

var
  somevar: reference; // will fail
  somevar:  // correct fix

=== code end ===

A function reference variable can then be called like any other function 
pointer type:


=== code begin ===

var
  p: TProcLongInt;
begin
  p := @SomeLongIntProc;
  p(42);
end.

=== code end ===

If a function reference has no parameters then you need to use "()" 
nevertheless in the FPC/ObjFPC modes like for other function pointer types:


=== code begin ===

type
  TProc = reference to procedure;
var
  p: TProc;
begin
  p := @SomeProcedure;
  p(); // required
  p; // this can be used e.g. in mode Delphi
end.

=== code end ===

Like other function pointer types they can also be declared anonymously 
as part of a variable, field declaration (but not as part of a paramater 
declaration):


=== code begin ===

var
  f: reference to function: LongInt;

type
  TTest = class
    f: reference to procedure;
  end;

=== code end ===

They get their great power from a point that is for once *not* 
considered an implementation detail: function references are in fact 
internally declared as reference counted interfaces with a single 
Invoke() method of the provided signature. So the above examples are in 
fact declared like this:


=== code begin ===

type
  TProcLongInt = interface(IInterface)
    procedure Invoke(aArg: LongInt); stdcall; overload;
  end;

  TFuncTObject = interface(IInterface)
    procedure Invoke(aArg: TObject): TObject; overload;
  end;

  generic TGenericProc = interface(IInterface)
    procedure Invoke(aArg: T); overload;
  end;

=== code end ===

This has a few implications:
- in the RTTI this will appear like a normal interface
- it reacts to the $M directive like a normal interface
- it is a managed type
- it has *no* valid GUID
- it can be implemented by a class
- it can be inherited from

Especially the last two points are important.

That the interface can be implemented means that much more functionality 
and state can be added to a function reference:


=== code begin ===

type
  TFunc = reference to function: LongInt;

  TSomeImpl = class(TInterfacedObject, TFunc)
    f: LongInt;
    function Invoke: LongInt;
  end;

function TSomeImpl.Invoke: LongInt;
begin
  Result := f;
end;

var
  t: TSomeImpl;
  f: TFunc;
begin
  t := TSomeImpl.Create;
  f := t;
  Writeln(f()); // will write 0
  t.f := 42;
  Writeln(f()); // will write 42
  f := Nil; // the usual warnings about mixing classes and interface apply!
end.

=== code end ===

As function references don't have valid GUIDs you can't however use 
QueryInterface() or the as-operator to retrieve it. Using the low level 
interface related