Recent

Author Topic: A syntactic change: blocks as statements  (Read 4934 times)

xixixi

  • New Member
  • *
  • Posts: 25
A syntactic change: blocks as statements
« on: June 17, 2023, 08:01:35 pm »
What do you think about changing the definition of structured statement from:

structured statement: compound statement
                      conditional statement
                      repetitive statement
                      with statement
                      exception statement

to:

structured statement: block
                      conditional statement
                      repetitive statement
                      with statement
                      exception statement

?

The change is backwards-compatible and allows to introduce inner scopes.

A sample of how code would look:
Code: Pascal  [Select][+][-]
  1. begin
  2.     DoThings;
  3.     // ....
  4.     WriteLn('Hashtable contents:');
  5.     var
  6.         k: string;
  7.     begin
  8.         for k in myhashtable.Keys do
  9.           const
  10.             v = myhashtable[k];
  11.           begin
  12.             WriteLn(k, ' -> ', v);
  13.           end;  // scope of v ends here
  14.     end;  // scope of k ends here
  15.     // ...
  16.     DoOtherUnrelatedThings;
  17. end;
  18.  

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 10691
  • Debugger - SynEdit - and more
    • wiki
Re: A syntactic change: blocks as statements
« Reply #1 on: June 17, 2023, 08:07:21 pm »
Apart from the new name: Old topic. "inline var declarations" (and the like) have been discussed lots and lots of times.

Search the old conversations. See what was already discussed (before repeating it yet another time).

Then, if you really have something that is truly groundbreaking new on the topic => present it, and show by direct comparison how it differs from the existing....

----
My 2 cents.

xixixi

  • New Member
  • *
  • Posts: 25
Re: A syntactic change: blocks as statements
« Reply #2 on: June 17, 2023, 08:25:53 pm »
Then, if you really have something that is truly groundbreaking new on the topic => present it, and show by direct comparison how it differs from the existing....

From the existing what? Proposals, or current language?

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 10691
  • Debugger - SynEdit - and more
    • wiki
Re: A syntactic change: blocks as statements
« Reply #3 on: June 17, 2023, 08:40:29 pm »
Where your proposal is different from the existing proposals. (Other than giving the idea a new name)

You are of course free to just repeat the exact same (or very similar) ideas/statements/proposals that have already be made.
But what is the point of it?

Or do you want to repeat the same and expect a different outcome.... ?  ;) SCNR


-- Just to add: This is my personal opinion. Not posting this as admin/moderator. So wherever this topic goes, at current is not limited.
« Last Edit: June 17, 2023, 09:20:35 pm by Martin_fr »

440bx

  • Hero Member
  • *****
  • Posts: 4905
Re: A syntactic change: blocks as statements
« Reply #4 on: June 17, 2023, 09:36:10 pm »
What do you think about changing the definition of structured statement from:
Instead of changing the definition of structured statement I would much prefer having inline scopes which gives the programmer everything inline variables provide and then some (scoped inline type and constant definitions along with breakable scoped statements, all of it fully in the spirit of J&W's Pascal.)

You can find an example of inline scopes at https://forum.lazarus.freepascal.org/index.php/topic,43172.msg323311.html#msg323311

That feature would allow writing significantly simpler and cleaner code and, would also allow the compiler to optimize code more easily.
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 10691
  • Debugger - SynEdit - and more
    • wiki
Re: A syntactic change: blocks as statements
« Reply #5 on: June 17, 2023, 09:46:09 pm »
Well, all of that actually already exist (but for the optimization).

In trunk, there are anonymous functions. Just inline one of them, including a call.
Code: Pascal  [Select][+][-]
  1. procedure Foo
  2. begin
  3.   DoFoo;
  4.   // Start scope or block or whatever you want to name it
  5.   procedure ()
  6.   var a: TBar;
  7.   begin
  8.   end(); // invoke here
  9.   ContinueFoo;
  10. end;

Since no reference is kept to the anonymous function, the compiler could easily optimize it. (Such optimization would have to be written in any case... So adding it here, is no harder than creating a new feature to which it then still has to be added).


Warfley

  • Hero Member
  • *****
  • Posts: 1855
Re: A syntactic change: blocks as statements
« Reply #6 on: June 17, 2023, 10:39:23 pm »
There are I think exactly 2 use cases where inline variables would be useful:
1. for For loops, because here you usually use the typical iterator names (i, j, k, m, etc.) and these are only used for this single loop, and having them in your variable definition just takes space without adding much information.
Also right now you are restricted to having only one type, inline variables would allow:
Code: Pascal  [Select][+][-]
  1. for var i: Integer in IterateIntegers do
  2.  
  3. for var i: QWord in IterateQWords do
Today if you have such a situation you need to to have seperate itaration variable for the other loop, and it happend to me more than once that I accidentally wrote the name of the variable of a previously used loop (I often just brainlessly type "i" as iterator variable, because I'm so used to it). Because those variables are available in the same function, it is easy to accidentally use them and it compiles happiely and you wonder why nothing is working.

The second point is for scoped lifetime, as managed records now provide the capability to have automatic lifetime management, one could imagine writing to a file like that:
Code: Pascal  [Select][+][-]
  1. FileStream.Open(FileName);
  2. FileStream.WriteLn('Hello File');
The problem is that the finalizer will only be called at the end of the function, meaning the file will stay open until then. So a solution to this may be to use scopes:
Code: Pascal  [Select][+][-]
  1. with var FileStream: TFileStream do
  2. begin
  3.   FileStream.Open('FileName');
  4.   FileStream.WriteLn('Hello File');
  5. end;

Aside from these two I don't see much reason to do so. When you are at a point where you have so many variables that you may get confused and need to introduce scoping, that is usually a sign that you are having to much code in one function, and should rather split it up into multiple functions.

Note that you can also use nested functions to retain scope:
Code: Pascal  [Select][+][-]
  1. procedure Foo(param: Integer);
  2.  
  3. var
  4.   x: Integer;
  5.  
  6. procedure PrintXAndParam;
  7. begin
  8.   WriteLn(x, param); // As nested function it has access to the variables defined before it and to the parameters
  9. end;
  10.  
  11. begin
  12.   x := 42;
  13.   PrintXAndParam;
  14. end;
That said, I think you should design your program in a way that you encapsulate your functionality such that you don't need to rely on much state anyway.

I have never found a program where a really big function was actually necessary and could not be encapsulated into multiple smaller functions.

Note that not having inline variable definitions was a key design decision for pascal by Wirth, where other languages at the time where not going that route, and the reason for this is that it can keep the code cleaner. That said of course if you have giant functions with paragraphs of variable definitions in the front, this can have the opposite effect, but as I said, in this case you should cleanup your code and not try to "fix" the language to work better with messy code.
« Last Edit: June 17, 2023, 10:44:37 pm by Warfley »

440bx

  • Hero Member
  • *****
  • Posts: 4905
Re: A syntactic change: blocks as statements
« Reply #7 on: June 17, 2023, 10:41:36 pm »
In trunk, there are anonymous functions. Just inline one of them, including a call.
Functionally that seems to implement local scopes, however, since the local scope is being implemented using an anonymous function/procedure, a stack frame, which is unnecessary in the case of a local scope, is created.

Thank you though, for some reason I had not thought about using the new anonymous functions to implement local scopes.
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 10691
  • Debugger - SynEdit - and more
    • wiki
Re: A syntactic change: blocks as statements
« Reply #8 on: June 17, 2023, 10:49:49 pm »
The problem is that the finalizer will only be called at the end of the function, meaning the file will stay open until then.
Is that so? As in, is that documented?

Because I recall that people couldn't use the "interface trick" for finalization, because unlike the non-documented behaviour in Delphi, Fpc would free them at an earlier time. Or maybe I recall it wrong, it's a long long time ago.

Warfley

  • Hero Member
  • *****
  • Posts: 1855
Re: A syntactic change: blocks as statements
« Reply #9 on: June 17, 2023, 10:55:34 pm »
In trunk, there are anonymous functions. Just inline one of them, including a call.
Code: Pascal  [Select][+][-]
  1. procedure Foo
  2. begin
  3.   DoFoo;
  4.   // Start scope or block or whatever you want to name it
  5.   procedure ()
  6.   var a: TBar;
  7.   begin
  8.   end(); // invoke here
  9.   ContinueFoo;
  10. end;
I know anonymous functions are really useful, but this syntax is so ugly and cluttery. I still believe that this was an April Fools joke by someone at Embarcadero, but he forgot to tell anyone so it was integrated into the language.

Is that so? As in, is that documented?

Because I recall that people couldn't use the "interface trick" for finalization, because unlike the non-documented behaviour in Delphi, Fpc would free them at an earlier time. Or maybe I recall it wrong, it's a long long time ago.
You are right it is undocumented, which makes it actually even worse for such cases (if it's documented it's at least predictable), but I remember from my own tests a few years ago that FPC would call it at the end of the function. At least when used as such:
Code: Pascal  [Select][+][-]
  1. with FileOpen do // Returning a Managed Record Filestream
  2.   WriteLn('Hello File');

It would be really neat if the with statement would have a defined scope lifetime for managed types. That said, I don't like the with statement because of it's shadowing, i.e. when you are in a with and both your current Self and the with have the same Identifiers it can get confusing (e.g. in the example above with Record.WriteLn vs System.WriteLn)

BeniBela

  • Hero Member
  • *****
  • Posts: 921
    • homepage
Re: A syntactic change: blocks as statements
« Reply #10 on: June 17, 2023, 10:56:40 pm »

Then, if you really have something that is truly groundbreaking new on the topic

Relatively new is that Delphi added inline var declarations


Now fpc needs it too for Delphi compatibility

Delphi compatibility is more important than syntax penchants

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 10691
  • Debugger - SynEdit - and more
    • wiki
Re: A syntactic change: blocks as statements
« Reply #11 on: June 17, 2023, 11:03:45 pm »

Then, if you really have something that is truly groundbreaking new on the topic

Relatively new is that Delphi added inline var declarations

Had been mentioned in previous discussions.

Warfley

  • Hero Member
  • *****
  • Posts: 1855
Re: A syntactic change: blocks as statements
« Reply #12 on: June 17, 2023, 11:18:24 pm »
Relatively new is that Delphi added inline var declarations

I understand why Embarcadero did this (to allow type inference, which is extremely valuabe especially with generics), but like with pretty much all their language design decisions, while the idea is decent, the implementation isn't.

The reason why Pascal has a fixed location for all variable definitions is so it is easy to reckognize where something is, and it keeps the actual functionality in the code clean from "boilerplate" code.
The problem with the new inline variables in Delphi is that they are to "easy", in the sense that when you can just write your variable definition inline there is no need to do the extra work to put them in the definition section of the header. This incentivises you to always prefer this, which results in less readable code, as adding a bunch of definitions inline as just statements will basically just add noise to the actual function of the code blocks it is in.

A much better way would have been to have an explicit structure around them, like with:
Code: Pascal  [Select][+][-]
  1. with var i := 42 do
  2.   // use i in with block

This allows for having scoped lifetime and visibility, seperates it clearly from instruction statements, and while being readable when used in moderation, exessive use of nested scoping withs will result in alot of boilerplate, incentivising to use the proper definition space whenever possible, and making this clearly an exception to the rule that should only be used when necessary.

A language should make it "painful" to write bad code and rewarding to write good code, and the upmost priority should always been writing readable code with as little noise as possible.
But Embarcadero is just really bad at making good design decisions.

xixixi

  • New Member
  • *
  • Posts: 25
Re: A syntactic change: blocks as statements
« Reply #13 on: June 17, 2023, 11:27:41 pm »
Well, all of that actually already exist (but for the optimization).

In trunk, there are anonymous functions. Just inline one of them, including a call.

That's exactly what I thought when I saw the announcement of anonymous functions; that having them it's only a small step to have inner blocks/scopes.

It isn't as straightforward though. Result and Exit need to be fixed to refer to the outer function, "free" break and continue need to be changed to refer to encompassing loops, and maybe goto need to be allowed to cross blocks in this case.

Maybe other fixes as well.
« Last Edit: June 17, 2023, 11:30:34 pm by xixixi »

xixixi

  • New Member
  • *
  • Posts: 25
Re: A syntactic change: blocks as statements
« Reply #14 on: June 17, 2023, 11:44:01 pm »
Instead of changing the definition of structured statement I would much prefer having inline scopes which gives the programmer everything inline variables provide and then some (scoped inline type and constant definitions along with breakable scoped statements, all of it fully in the spirit of J&W's Pascal.)

You can find an example of inline scopes at https://forum.lazarus.freepascal.org/index.php/topic,43172.msg323311.html#msg323311

That feature would allow writing significantly simpler and cleaner code and, would also allow the compiler to optimize code more easily.

Sure. It's a good idea for inner scopes to have a header. Actually, it would be necessary if the code shown by Martin_fr ends up being valid, since a block can start with any of label, type, const, var, procedure, function, etc... I thought none of those keywords could start a statement, but if that isn't the case, then a header is needed.

 

TinyPortal © 2005-2018