Lazarus

Free Pascal => General => Topic started by: nouzi on November 11, 2018, 02:07:38 pm

Title: Question ?!!!!
Post by: nouzi on November 11, 2018, 02:07:38 pm
You could have this in free pascal ?
http://blog.marcocantu.com/blog/2018-october-inline-variables-delphi.html?fbclid=IwAR208x_u_TDY1iRILrxn3eZ-IbSFZPq_P_pLmRSY_V5WO-z6A6d1nbbLMB8
Title: Re: Question ?!!!!
Post by: howardpc on November 11, 2018, 02:38:38 pm
FPC introduced initialisation of variables in their declaration long before Delphi.
One drawback of syntax sugars that, for example, make the compiler infer and allocate implicit types to variables, is that they inevitably slow the compiler slightly, and make it that bit more complex and more time-consuming/harder to maintain.

Not to mention that they move Pascal further away from its Wirthian type-safe declarative design.
Title: Re: Question ?!!!!
Post by: Thaddy on November 11, 2018, 03:02:26 pm
FPC introduced initialisation of variables in their declaration long before Delphi.
One drawback of syntax sugars that, for example, make the compiler infer and allocate implicit types to variables, is that they inevitably slow the compiler slightly, and make it that bit more complex and more time-consuming/harder to maintain.

Not to mention that they move Pascal further away from its Wirthian type-safe declarative design.
You're partially barking up the wrong tree, Howard. (Sorry, just let the dogs out  8-), actual dogs, two of them )
What he is referring to is:
Code: Pascal  [Select][+][-]
  1. program testinlinevars;
  2. begin
  3.   // imagine lots of previous code
  4.   for var i:integer := 1 to 10 do writeln(i);
  5. end.

Or even with type inference:
Code: Pascal  [Select][+][-]
  1. program testinlinevars;
  2. begin
  3.   for var i  := 1 to 10 do writeln(i);
  4. end.

Such code has been requested many times and always refused by the compiler team. In my opinion for all the right reasons.
Yes. The declarative design of Pascal is a feature and a huge asset. Working with C code bases for the last 30 years this kind of syntax should never be introduced and is often forbidden in huge C codebase examples like the Linux kernel.
Title: Re: Question ?!!!!
Post by: Handoko on November 11, 2018, 03:09:27 pm
The reasons for the rejection can be found here: (item #11)
http://wiki.freepascal.org/Modernised_Pascal
Title: Re: Question ?!!!!
Post by: Thaddy on November 11, 2018, 03:12:14 pm
The reasons for the rejection can be found here: (item #11)
http://wiki.freepascal.org/Modernised_Pascal
That's only one of the reasons. There are many more to be found on the dev mailing list. Or even the original papers on the design of the Pascal language by Niklaus Wirth.
Title: Re: Question ?!!!!
Post by: nouzi on November 11, 2018, 03:47:37 pm
thank for all
Title: Re: Question ?!!!!
Post by: dpremus on November 23, 2018, 08:04:07 pm
I hope that we will never have inline variables in FPC.

This approach in C is used for having better performance, but now day compilers should be smart enough to optimize this.

This will introduce more mess in code than benefits.

Do we need Delphi compatibility anymore?

For example, you can't still use a string in Delphi "case" and they talk about language improvements.
Title: Re: Question ?!!!!
Post by: marcov on November 23, 2018, 08:11:16 pm
In the initial discussion I missed it, but the below illustrates the problem perfectly

Code: [Select]

procedure xxx.yyy;
var thisisastaticglobalvar : integer =0;
begin
  var thisisalocalvarbutthesyntaxisthesame: integer =0;
  ..
end;

Same syntax, two lines apart, meaning totally different. This is not just a dig at Embarcadero. The mode objfpc initialized variables just add to the confusion by recycling syntax for initialized local variables;

Code: [Select]
{$mode objfpc}
procedure xxx.yyy;
var weknoweverythingbetterandinfpcthisisaninitializedlocalvar  : integer =0;
begin
  var thisisalocalvarbutthesyntaxisthesame: integer =0;
  ..
end;

Sigh.

Moral of the story: don't recycle syntax for something potentially ambiguous.

"you don't have to use it if you don't like it" is NOT a good argument.
Title: Re: Question ?!!!!
Post by: User137 on November 23, 2018, 09:44:50 pm
Not sure i understand the explanations. Variable scope is same, and this sort of thing is clearly restricted:
Code: Pascal  [Select][+][-]
  1. var
  2.   Form1: TForm1;
  3.   Form1: TStringList;
You'll get: Error: Duplicate identifier "Form1". Same should happen if you try to re-declare a variable inside a function, before or after the "begin" word.

Code: Pascal  [Select][+][-]
  1. procedure xxx.yyy;
  2. var i: integer = 0;
  3. begin
  4.   var i: integer =0; // Illegal!
  5.   var k: integer =0; // Ok.
  6.   for var n:integer := 1 to 10 do writeln(n); // Ok.
  7.   // variable n doesn't exist here anymore, but k does.
  8.   for var n:integer := 1 to 10 do writeln(n); // Ok.
  9. end;
Title: Re: Question ?!!!!
Post by: jamie on November 23, 2018, 11:10:59 pm
Random variable declaration is a bad idea, very sloppy code however, I do like the idea of
the FOR LOOP control being able to do this because of this simple fact. The loop variable is documented
as undefined out side the FOR LOOP so it would make perfect sense to allow this to take place within
the loop control where the code in the loop would be the only code that can see it.

 The FOR LOOP is not designed to allow the loop variable to be used outside so why not simply allow the
FOR loop control to create a localized variable as am option..

 The WHILE and REPEAT do reserve the ending value of the a loop while the FOR does not depending on what
the compiler decides to do .

 This is my argument unless you want to modify the FOR LOOP control to have a usable ending value when exiting the
block.


Title: Re: Question ?!!!!
Post by: Martin_fr on November 23, 2018, 11:44:57 pm
Random variable declaration is a bad idea, very sloppy code however, I do like the idea of
the FOR LOOP control being able to do this because of this simple fact. The loop variable is documented
as undefined out side the FOR LOOP
IIRC, with the exception when the loop was exited by "break" or the like, in which case it is defined? (need to double check)

Beside search the many discussions on this forum, where there are plenty of reasons why even the for loop var would not be a good idea. (And yes, I did read the arguments that were brought in favour, and none prevailed)

And lastly, if the only concern is, not to accidentally use the var after the loop:
- the compiler should emit a "undefined warning" => if not that would be something that you should request. If it does, -we promote warnings to errors.
- and if that is not good enough, and you really think it needs changed syntax / extra features (I don't, but I humour the idea): in the var block on top "var a: TEnumerable loopcounter;" limit it to be used as loop counter, and only avail in loops in which it is a counter. I don't think that is needed, but it is far less problematic, and solves the problem.
Title: Re: Question ?!!!!
Post by: BeniBela on November 24, 2018, 12:34:24 am
Delphi compatibility is important

All kinds of weird things were added for Delphi compatibility. classes, when there are already objects; interfaces; Delphi's generic syntax; codepage aware strings ...

This syntax should not be the reason to abandon Delphi compatibility
Title: Re: Question ?!!!!
Post by: 440bx on November 24, 2018, 01:33:20 am
Do we need Delphi compatibility anymore?
More people should ask themselves that question.  The world is afraid of C/C++, that leads to choices like Delphi compatibility because of the (justified) fear that a better language would not stand a chance against the popularity that mediocre languages have gained.   Very unfortunate.
Title: Re: Question ?!!!!
Post by: PascalDragon on November 24, 2018, 02:48:39 pm
Delphi compatibility is important

All kinds of weird things were added for Delphi compatibility. classes, when there are already objects; interfaces; Delphi's generic syntax; codepage aware strings ...

This syntax should not be the reason to abandon Delphi compatibility
On the contrary. This syntax is a good reason to abandon Delphi compatibility, because unlike the ones you mentioned this one touches and chances the very core spirit of the Pascal language.

As such the opinion of the development team on this feature is that we will not implement this. FPC has a strong user base by itself as such we can be picky nowadays which nonsense of Delphi we accept and which we don't.

In the initial discussion I missed it, but the below illustrates the problem perfectly

Code: [Select]

procedure xxx.yyy;
var thisisastaticglobalvar : integer =0;
begin
  var thisisalocalvarbutthesyntaxisthesame: integer =0;
  ..
end;

Same syntax, two lines apart, meaning totally different. This is not just a dig at Embarcadero. The mode objfpc initialized variables just add to the confusion by recycling syntax for initialized local variables;

Code: [Select]
{$mode objfpc}
procedure xxx.yyy;
var weknoweverythingbetterandinfpcthisisaninitializedlocalvar  : integer =0;
begin
  var thisisalocalvarbutthesyntaxisthesame: integer =0;
  ..
end;

Sigh.

Moral of the story: don't recycle syntax for something potentially ambiguous.

"you don't have to use it if you don't like it" is NOT a good argument.
Ehm... where was this mentioned? The syntax for initializing inline variables in Delphi is
Code: Pascal  [Select][+][-]
  1. procedure xxx.yyy;
  2. begin
  3.   var thisisalocalvarbutthesyntaxisthesame: integer := {!} 0;
  4. end;
  5.  
(Note the ":=" instead of "=")

And where was it mentioned that Delphi now supports the following?
Code: Pascal  [Select][+][-]
  1. procedure xxx.yyy;
  2. var thisisastaticglobalvar : integer = 0;
  3. begin
  4. end;
  5.  
And that this is a global variable now merely by being initialized?
Title: Re: Question ?!!!!
Post by: Leledumbo on November 27, 2018, 09:04:08 pm
As soon as this gets implemented, codetools will have to work harder by searching both declaration and execution section, just as your eyes do. Principle of locality in Pascal spirit is implemented through nested procedure, not inline declarations (and single called nested procedure should be inline-able automatically, zeroing the overhead).
Title: Re: Question ?!!!!
Post by: LemonParty on November 28, 2018, 09:51:29 am
Code: Pascal  [Select][+][-]
  1. procedure XXX;
  2. var S: String;
  3.  
  4.  procedure Append(Str: String);
  5.  begin
  6.   S:= S + Str;
  7.  end;
  8.  
  9. begin
  10.  Append('apple');
  11.  Append('1');
  12. end;
Try to use inline variables with this code.
Title: Inline variable declatations
Post by: philtroy on June 08, 2019, 09:00:25 pm
Hi

I am new to this forum, and to Free Pascal, but not to Pascal.  I started programming in 1970, and I used Turbo Pascal to write the analysis software used for my doctoral dissertation.  I then used Delphi for several years, before moving on (and perhaps backwards) to Java around 15 years ago.  So here I am at an advanced age still working, and still doing some computer programming (as part of my analytics job).

I am looking for a modern programming language to use to build analytics capabilities for my organization.  Some of those capabilities require user interfaces.  I would really like to jump in and use Free Pascal (I work on Linux mostly but most of my users use Windows) and I really only have two issues with it.  And one of them is the lack of an ability to use inline variable declarations (I do not want and do not totally believe in the value of type inference so that is not an issue for me).  (FYI, I have used C++ and get a sick feeling in my stomach every time I think of that experience, and have looked at Rust, Golang, Kotlin, and Swift and found them all to be wanting for my purposes.)

So why do I feel that inline variable declaration is so important?  From a very practical perspective, less lines of code makes for easier to understand and support code.  If I can save 10 lines of variable declarations by using inline variable declarations it makes it easier for me to follow the whole piece of code.  And I would venture to say for most other people to follow, not only because there are less lines of code, but also because variable declarations can in many cases be closer to where the variables are being used.

I am sure that there are many reasons for not using inline variable declarations (though I cannot think of them right now).  So, why not allow individuals or organizations to choose their own coding standards.  I would be willing to bet a pitcher or two of beer that most would want to use inline variable declarations, but that would be their choice.

In my mind, the best reason for not implementing inline variable declarations, is that it would be hard to do so.  I am not a computer scientist and I do not have experienced developing compilers so I would not know for sure whether that would be the case.  But I did take an introduction to computer science course with Alan Perlis (and if you do not know who he is it might be interesting for you to find out by googling him) sometime around 1984-1985 while a doctoral student at Yale University.  And I seem to remember that in most compilers all local variables are declared in a stack frame on the stack.  Which suggests to me that it might not be so hard to allow new variables to be added to the stack frame at any time, and that the biggest issue might be to make sure that these new variables are not referenced before that point in time.  This in turn might constrain that variable declarations would need to occur in an unambiguous manner before they are being used (but I leave that for the computer scientists).

I have one other comment, which has to do with the declaration that the compiler team would not agree to to make this change.  And this comment is meant to be constructive.  If the community (which I just joined and thus have little say in it) wishes for a feature to be added, perhaps the role of the development team should be discuss the relative merits of implementation of the feature, and the feasibility of the feature, but to then support the decision of the community as to whether the feature is actually implemented. To me, that is what volunteering and community are about, and yes, in my many years of living on this beautiful planet, I have done a little volunteering.

Phil Troy

P.S. Apparently one of Dr. Perlis's famous quotations is "Fools ignore complexity. Pragmatists suffer it. Some can avoid it. Geniuses remove it."  So I suggest that we do our best effort to remove the complexity involved in trying to follow long programs by carefully identifying language features that make those programs shorter without making them more complex.
Title: Re: Question ?!!!!
Post by: marcov on June 08, 2019, 09:36:42 pm
The inline variable discussion raged a few months ago after Delphi announced, and the end decision was to not implement or rediscuss it for the next few years. (and that's only because we've learned to never say never)

So if you really want inline variables, best look elsewhere.

P.s. willy-nilly mixing varying types of lines is IMHO not about reducing complexity. It is increasing it.

Title: Re: Inline variable declatations
Post by: 440bx on June 08, 2019, 10:02:05 pm
P.S. Apparently one of Dr. Perlis's famous quotations is "Fools ignore complexity. Pragmatists suffer it. Some can avoid it. Geniuses remove it."  So I suggest that we do our best effort to remove the complexity involved in trying to follow long programs by carefully identifying language features that make those programs shorter without making them more complex.
Hello Phil,

You already got a pretty clear answer on the inline variables situation. 

Alan Perlis had a lot thought inducing one-liners. :)

The current state of computer language design reminded me of a couple of them...

1. Humans get cancer, Computer Science gets C.
2. C++ is metastasized C.

Someone asked "Why create mediocrity, when you can copy genius?" and the answer is, because it is much easier to copy mediocrity than genius.  (it doesn't take a genius to figure that out.)

Title: Re: Question ?!!!!
Post by: VTwin on June 08, 2019, 11:43:42 pm
I agree with the objections to inline variables, which, imho, add complexity, and avoided them even when available. If a procedure is so long that it is difficult to scroll to the top to find the variables, it is probably too long. I like knowing where they are declared.

Harking back to early FORTRAN, one could simply use a variable without declaring it. Programming was so uncomplicated back then! :D
Title: Re: Question ?!!!!
Post by: jamie on June 09, 2019, 06:16:00 pm
Yes I fully don't want random inline variables scattered all over the place within a block of
code. I Hated that in C/C++, was very hard to follow, especially when they redeclare it as
a different type on the fly... That is a bad idea..

 All variables associated with the block of code should be nested together in a designated location
like they are now..

 However,,,, I Still think for a FOR LOOP control, it should be able to create its own variable within
the FOR LOOP setup and keep the name space local to that FOR control.

  An inner FOR LOOP block of course can see a previous FOR LOOP variable but any code should not
be able to see forward declarations of FOR and Integrated LOOP variable..

 Since these variables are undefined after the loop and are unsafe to use why should the be
visible to code outside ?
The same mechanism used for the "WITH" can also be used here.

 And that's my argument which I know will go no where.

Title: Re: Question ?!!!!
Post by: ASerge on June 09, 2019, 09:00:17 pm
If a procedure is so long that it is difficult to scroll to the top to find the variables, it is probably too long.
+1
In Pascal there is such a wonderful tool like nested functions. Logically independent part of the code is better extract to a separate function, where to declare the variables necessary for it. This reduces complexity because you see less code at a time. Secondly, you also document it by assigning a suitable function name.
For example, in "C" this is not possible, so it had to invent the ability to declare variables anywhere :)

However,,,, I Still think for a FOR LOOP control, it should be able to create its own variable within
the FOR LOOP setup and keep the name space local to that FOR control.
...
The same mechanism used for the "WITH" can also be used here.
For for may be, but for with...
It seems to me that the with instruction increases the complexity. Inside it, I have to think about each property/function: it refers to a Self or to a variable in "with". So I generally try to avoid it.
Title: Re: Question ?!!!!
Post by: 440bx on June 10, 2019, 01:35:42 am
If a procedure is so long that it is difficult to scroll to the top to find the variables, it is probably too long.
+1
In Pascal there is such a wonderful tool like nested functions. Logically independent part of the code is better extract to a separate function, where to declare the variables necessary for it. This reduces complexity because you see less code at a time. Secondly, you also document it by assigning a suitable function name.
Nested functions are a very nice feature when a particular sequence of code is used more than once in a specific function/procedure and no place else.  The keywords are "more than once".  If the sequence of code is used only once then it could have been coded inline and that would have spared the programmer from having to "jump" to their definition to follow the logical flow.

Easy to understand code isn't a function (no pun intended) of how long the function/procedure is.  It's affected a lot more by how many times the programmer's attention has to jump to another location to follow the logical flow.  When code is broken into umpteen pieces that are executed only once, the code resembles more a jigsaw puzzle than a program.  It doesn't take goto-s to create logic flow that is quite reminiscent of spaghetti code.

It's much easier to understand a 500 line function that is totally linear in its execution than one that does the same thing but is broken into 10 (or more) pieces.  You don't have to re-assemble the pieces in your mind and have your focus diverted from the logic just as many times.

For example, in "C" this is not possible, so it had to invent the ability to declare variables anywhere :)
That's not the reason they "invent"ed inline variable declarations. Some C compilers support nested functions (an extension) _and_ inline variable declarations. 

However,,,, I Still think for a FOR LOOP control, it should be able to create its own variable within
the FOR LOOP setup and keep the name space local to that FOR control.
...
The same mechanism used for the "WITH" can also be used here.
For for may be, but for with...
It seems to me that the with instruction increases the complexity. Inside it, I have to think about each property/function: it refers to a Self or to a variable in "with". So I generally try to avoid it.
Poor "with" statement, it gets a bad rap because programmers either misuse it or abuse it.  Used correctly, it is a very nice Pascal feature.  Surprising that the C++ folks haven't copied it.

It would be extremely nice if a limited version of inline variable declaration was added to Pascal.  The "for" loop is the most obvious candidate.

Title: Re: Question ?!!!!
Post by: philtroy on June 10, 2019, 08:21:05 am
Hi

In all seriousness, I thank you all and very much appreciate both the seriousness and the humor of the responses.

:-)

Phil Troy

Title: Re: Question ?!!!!
Post by: Zoran on June 10, 2019, 12:20:05 pm
Oracle's PL/SQL language (which has a Pascal-like syntax - use begin-end for blocks, has var declaration section above code, use procedure/function keywords with pascal-like declaration syntax, nested procedures in procedures) have had variables with block scope for a long time already.

Their syntax is in my opinion much more elegant than what Embarcadero introduced. Every begin-end block (so not only the routine level block,  but any unnamed block) can have it's own var section. So, something like this is allowed:

procedure Proc;
var
  X: Integer; // a variable with procedure scope
begin
  // some code
  var
    Y: Integer; // variable Y has block scope
  begin
     // varible Y is accesible only within this block.
  end;
  // Here, Y is out of scope
end;

So, var section must be just above begin keyword. Then varible has block-scope.
Then, these are truly block-scope variables, not just "inline variables", that Emarcadero introcuded.

I don't think that FPC should add these -- I understand that the options are either implement it in Delphi compatible way, or not at all.
Then, I prefer "not at all".
Title: Re: Question ?!!!!
Post by: ASerge on June 10, 2019, 03:34:39 pm
Nested functions are a very nice feature when a particular sequence of code is used more than once in a specific function/procedure and no place else.  The keywords are "more than once".  If the sequence of code is used only once then it could have been coded inline and that would have spared the programmer from having to "jump" to their definition to follow the logical flow.
Absolutely the opposite opinion. Not exactly "more than once", i.e. just allocate a piece of code to a separate procedure, even if only once, that's good. The amount of code is limited to a small function, you check it, make sure everything is OK and forget. Then later, at the mention of the name, everything becomes clear. But to keep 500 lines of code in memory - that's really too difficult. At the same time, using "inline" for such functions you can not care about performance.
Title: Re: Question ?!!!!
Post by: 440bx on June 10, 2019, 03:56:28 pm
So, var section must be just above begin keyword. Then varible has block-scope.
Then, these are truly block-scope variables, not just "inline variables", that Emarcadero introcuded.
what would be really nice would be to extend the concept of functions and procedures all the way down to scopes.  Instead of defining a function/procedure, define a named scope (the name would only be a "documentation" feature - not really necessary. )

A scope has the same characteristics as a function/procedure except it is not callable.  It can only be inside a function/procedure.  That is fully consistent with the essence of Pascal and offers some very nice abilities.  For instance...
Code: Pascal  [Select][+][-]
  1. SomeProc(parameters : types, ...);
  2. const
  3.   aconst : 123;
  4. type
  5.   sometype = 1..10;
  6. var
  7.   whatever : sometype;
  8. begin
  9.   statement;
  10.   statement;
  11.   ...
  12.   scope step1;
  13.   { any definitions/declarations within a scope are local to the scope }
  14.     type
  15.       scopetype = sometype;
  16.     const
  17.       scopeconst = 3;
  18.     var
  19.       scopevar : integer;
  20.   begin
  21.     statement;
  22.     statement;
  23.  
  24.     if somecondition then break; { breaks out of the scope - not the function/procedure - just like in a loop }
  25.  
  26.     statement;
  27.     statement;
  28.   end;
  29.  
  30.   scope step2;
  31.   begin
  32.    statement;
  33.    statement;
  34.    ...
  35.   end;
  36. end;
  37.  

that allows logically grouping statements within a function/procedure.  It also gives the ability to short-circuit (by the use of break) the logical flow within a scope.  The other very nice thing is that there should be significantly fewer variables declared at the function/procedure scope since any and all supporting/helper variables only exist within local scopes.  IOW, fewer "global" function/procedure variables.

Such a feature would simplify a lot of code and make it a lot easier to understand it and maintain it.

Rather unlikely that something like that will be implemented these days.  Too useful.

ETA:

@Serge

Absolutely the opposite opinion. Not exactly "more than once", i.e. just allocate a piece of code to a separate procedure, even if only once, that's good. The amount of code is limited to a small function, you check it, make sure everything is OK and forget. Then later, at the mention of the name, everything becomes clear. But to keep 500 lines of code in memory - that's really too difficult. At the same time, using "inline" for such functions you can not care about performance.
The thing is the programmer doesn't have to keep the 500 lines of code in mind.  All a programmer needs to have in mind is how he/she got to the statement he/she is inspecting, not the whole shebang. 
Plus, even if what you're saying were the case, it is still easier to keep 500 lines of code in mind than the same 500 lines of code _plus_ the 10 function/procedures the code has been broken into, not to mention to also have to keep in mind the _sequence_ in which those functions/procedures have been called.

I know we have a different opinion on that and the great majority of people will see it your way because that's what's been ingrained early in their minds.

It's not the number of lines of code that make a program hard to follow and understand, it's how many times the focus is redirected to some other place/function/procedure/whatever.  Having to constantly take one's focus from one place to another is the essence of spaghetti code. 

Title: Re: Question ?!!!!
Post by: Thaddy on June 10, 2019, 04:41:26 pm
[It would be extremely nice if a limited version of inline variable declaration was added to Pascal.  The "for" loop is the most obvious candidate.
Actually, have a look at this:
Code: Pascal  [Select][+][-]
  1. while true do;
But that looks more like type inference  ::)
Title: Re: Question ?!!!!
Post by: SymbolicFrank on June 10, 2019, 05:31:52 pm
Btw, if you break out of a for loop, the variable retains its value.
Title: Re: Question ?!!!!
Post by: marcov on June 10, 2019, 05:35:31 pm
Btw, if you break out of a for loop, the variable retains its value.

Is that documented or empirical evidence (read: compiler quackery )
Title: Re: Question ?!!!!
Post by: SymbolicFrank on June 10, 2019, 05:41:15 pm
From the docs:

Code: [Select]
The value of the loop variable is undefined after a loop has completed or if a loop is not executed at all.
If the loop was terminated prematurely with an exception or a break statement, the loop variable retains the
value it had when the loop was exited.
Title: Re: Question ?!!!!
Post by: Thaddy on June 10, 2019, 05:58:08 pm
I believe it was explained by Jonas somewhere on the bug tracker or the mailing list a couple of years ago:
- if a for loop fully executes then the variable is undefined.
- if a for loop exits prematurely with break, the variable is defined

I can't remember the reasons.. There were a whole lot of discussions because the difference in behavior of the counter in Delphi and FPC when the for loop is fully done.

I guess it is like this:
The value is preserved within the realms of the for loop range. If the full range is satisfied, it becomes undefined.
Hence in the case of break, the value is preserved since it is within the range.

But I can't find the evidence. [edit] I missed the response from SymbolicFrank, that proves it is documented in the official documentation.
Title: Re: Question ?!!!!
Post by: SymbolicFrank on June 10, 2019, 06:01:36 pm
It's useful: you probably want to know it when you break out of the loop: "Found it, this one!".
Title: Re: Question ?!!!!
Post by: marcov on June 10, 2019, 06:02:37 pm
If documented, it is of course ok.
Title: Re: Question ?!!!!
Post by: 440bx on June 10, 2019, 07:13:55 pm
It's useful: you probably want to know it when you break out of the loop: "Found it, this one!".
I'm sure this comment won't be very appreciated by Pascal lovers but, in C/C++ the value of the "for" index variable (if any) is stable.  There are no cases when it is undefined and other cases when it is defined.

That's nice.  OTH, the compiler has to work quite a bit harder when optimizing "for" loop code.  (compilers should work hard anyway.)

In Pascal, if you need to rely on the value of the indexing variable then you have to change the "for" loop into a "while" loop.  I've lost count of the number of times I've forgotten to increment the indexing variable in such translated loops.  Fortunately, the result and the cause are immediately discernible.







Title: Re: Question ?!!!!
Post by: SymbolicFrank on June 10, 2019, 10:03:53 pm
well, you declare it in the var section, retaining the value would make it consistent behaviour. I wouldn't mind.
Title: Re: Question ?!!!!
Post by: Zoran on June 11, 2019, 10:54:01 am
So, var section must be just above begin keyword. Then varible has block-scope.
Then, these are truly block-scope variables, not just "inline variables", that Emarcadero introcuded.
what would be really nice would be to extend the concept of functions and procedures all the way down to scopes.  Instead of defining a function/procedure, define a named scope (the name would only be a "documentation" feature - not really necessary. )

A scope has the same characteristics as a function/procedure except it is not callable.  It can only be inside a function/procedure.  That is fully consistent with the essence of Pascal and offers some very nice abilities.  For instance...
Code: Pascal  [Select][+][-]
  1. SomeProc(parameters : types, ...);
  2. const
  3.   aconst : 123;
  4. type
  5.   sometype = 1..10;
  6. var
  7.   whatever : sometype;
  8. begin
  9.   statement;
  10.   statement;
  11.   ...
  12.   scope step1;
  13.   { any definitions/declarations within a scope are local to the scope }
  14.     type
  15.       scopetype = sometype;
  16.     const
  17.       scopeconst = 3;
  18.     var
  19.       scopevar : integer;
  20.   begin
  21.     statement;
  22.     statement;
  23.  
  24.     if somecondition then break; { breaks out of the scope - not the function/procedure - just like in a loop }
  25.  
  26.     statement;
  27.     statement;
  28.   end;
  29.  
  30.   scope step2;
  31.   begin
  32.    statement;
  33.    statement;
  34.    ...
  35.   end;
  36. end;
  37.  

that allows logically grouping statements within a function/procedure.  It also gives the ability to short-circuit (by the use of break) the logical flow within a scope.  The other very nice thing is that there should be significantly fewer variables declared at the function/procedure scope since any and all supporting/helper variables only exist within local scopes.  IOW, fewer "global" function/procedure variables.

Such a feature would simplify a lot of code and make it a lot easier to understand it and maintain it.

Rather unlikely that something like that will be implemented these days.  Too useful.

ETA:

@Serge

Absolutely the opposite opinion. Not exactly "more than once", i.e. just allocate a piece of code to a separate procedure, even if only once, that's good. The amount of code is limited to a small function, you check it, make sure everything is OK and forget. Then later, at the mention of the name, everything becomes clear. But to keep 500 lines of code in memory - that's really too difficult. At the same time, using "inline" for such functions you can not care about performance.
The thing is the programmer doesn't have to keep the 500 lines of code in mind.  All a programmer needs to have in mind is how he/she got to the statement he/she is inspecting, not the whole shebang. 
Plus, even if what you're saying were the case, it is still easier to keep 500 lines of code in mind than the same 500 lines of code _plus_ the 10 function/procedures the code has been broken into, not to mention to also have to keep in mind the _sequence_ in which those functions/procedures have been called.

I know we have a different opinion on that and the great majority of people will see it your way because that's what's been ingrained early in their minds.

It's not the number of lines of code that make a program hard to follow and understand, it's how many times the focus is redirected to some other place/function/procedure/whatever.  Having to constantly take one's focus from one place to another is the essence of spaghetti code.

Yes, these "scopes" would be very nice syntax, quite contrary to new Delphi's "inline vars".
I fully agree with everything said in this post.

However, Emarcadero took quite different way, and I would rather not see any inline variables allowed, than what Delphi introduced.

Title: Re: Question ?!!!!
Post by: Thaddy on June 11, 2019, 11:50:01 am
1. Without reference to what C/C++ compiler(s) it can still be implementation dependent. I can't find any specifications for stable loop count values after exit.
2. Pascal is all about separating declaration from implementation, so Delphi made a big mistake here.
As I wrote before: given that language feature I hope FPC never introduces inline vars. It may be a convenience to the programmer but it is a nightmare for teams and to debug such a feature.
As I also wrote before: many mainline codebases in C/C++ forbid its use for that exact same reason.

That said: type inference for loop variables would be nice and likely easy to implement since those are always ordinals.
That would also prevent re-use after the loop.
Title: Re: Question ?!!!!
Post by: Blade on April 24, 2020, 09:35:44 am
1. Without reference to what C/C++ compiler(s) it can still be implementation dependent. I can't find any specifications for stable loop count values after exit.
2. Pascal is all about separating declaration from implementation, so Delphi made a big mistake here.
As I wrote before: given that language feature I hope FPC never introduces inline vars. It may be a convenience to the programmer but it is a nightmare for teams and to debug such a feature.
As I also wrote before: many mainline codebases in C/C++ forbid its use for that exact same reason.

That said: type inference for loop variables would be nice and likely easy to implement since those are always ordinals.
That would also prevent re-use after the loop.

I agree with this sentiment of not introducing inline variables and for the Free Pascal team to be very cautious and picky about anything Embarcadero introduces into Delphi.  If it is something to be considered, then possibly have it as something that can be converted over from Delphi to Lazarus or under a Delphi compatibility mode feature. 

It should be mentioned that Embarcadero has the C++Builder product, and an incentive to blur the lines between their C++ and Object Pascal (Delphi) products.  Even if it means introducing destructive changes to Delphi.  They might think such changes can snag a few more C language family users for a bump in sales.  Embarcadero's perspective can be very short-sighted and for just short term gains, something history has shown.  The Free Pascal team is debatably in a better position to look at the long view, and what's in the best interest of the language.  A lot of people use or will want to use Object Pascal, because it's not C++ and does things differently.
Title: Re: Question ?!!!!
Post by: avra on April 24, 2020, 12:17:12 pm
I do not like inline variables because of the bad debugging feeling experience in languages that support them.

The way I see it there are 2 reasons for users asking such a feature:
1) To avoid jumping each time to var section when you need new variable in the middle of some lengthy method
2) To quickly see variable type when variable is in the middle of the code and you are looking at the code or debugging it - and you want to avoid jumping to var section

First can be solved with the editor that on your request just asks for the type of a variable and automatically adds it into var section. Second can be solved by showing some on mouse hint with variable type in both editor and debugger.

Most native compiled languages having inline variables were made in the time when we had 25x80 character terminals without any graphics, so today's perspective is different and we have much better ways to address the problem then breaking the pascal spirit.

As for inline variables in for loop:
Code: Pascal  [Select][+][-]
  1. for var i: integer := 1 to 10 do
I am much more tolerant to such request although it is just a softer version of the general inline variables. I don't like it much, but I can look at it in the code without bad feeling in the stomach.

Although I see the advantage that in suggested example loop variable is not limited to integer types, I guess that most of it's use would be limited to that. Therefore, I would prefer to see this instead:
Code: Pascal  [Select][+][-]
  1. for 10 times do
That would be more in the spirit of pascal, and it would stay a readable sentence - which is in my opinion a crucial pascal feature. Of course, instead of 10 you could use any already declared integer like variable. It would have limited use (no easy way to reference counter in for-loop code), so at the end not that much needed either.

However I do think that we are missing some syntax sugar. For example implementing unified try-except-finally block would bring more clarity to complex code since FreePascal does not have garbage collector and we already have to use try-finally block in order to avoid memory leaks and make sure that each object creation always ends with destruction:
Code: Pascal  [Select][+][-]
  1. try
  2.   ..
  3. except
  4.   ..
  5. finally
  6.   ..
  7. end;
Title: Re: Question ?!!!!
Post by: 440bx on April 24, 2020, 12:47:46 pm
I do not like inline variables because of the bad debugging feeling experience in languages that support them.
What problems have you experienced ?... I use them in C and find the availability of that feature quite convenient and useful to produce simpler, easier to maintain code (provided the feature isn't abused/misused.)

IMO, part of the real problem is that the keywords "begin" and "end" in Pascal are already quite overloaded and overloading them even more to turn them into a limited form of scope delimiters will only make their inherent problems worse.

Inline variables is a nice feature provided it is well implemented.  The Embarcadero implementation is typical, throw some code at the computer, make it sort of work and call it a feature.  That will be $1500.00, thank you very much.  Not to mention that it adds another "Delphi can do what C does" fuzzy feeling for Delphi programmers to enjoy.



Title: Re: Question ?!!!!
Post by: avra on April 24, 2020, 01:21:02 pm
I do not like inline variables because of the bad debugging feeling experience in languages that support them.
What problems have you experienced ?... I use them in C and find the availability of that feature quite convenient and useful to produce simpler, easier to maintain code (provided the feature isn't abused/misused.)
As I said it was more of a bad subjective feeling then a real problem. Inline variables are not such common habit as people would think, so when looking at other people's code before I am aware of them I end up jumping to the wrong places and loosing time. And having an inline variable used for something few lines later is one thing, but used for something in 3 different far apart places when method is pages long... well, to me that's not much different from some C like for-loop written by some 'hacker' that will waste 10 minutes of my time every six months when I have to look at it again. Nothing that a good editor or different mind set can't deal with, but when you are forced to work with many different IDE's and editors you can not be familiar with more then 2 or 3.

Inline variables is a nice feature
We can agree that we disagree. I do not have a problem to stay it that way.
Title: Re: Question ?!!!!
Post by: munair on April 24, 2020, 01:28:37 pm
The way I see it there are 2 reasons for users asking such a feature:
1) To avoid jumping each time to var section when you need new variable in the middle of some lengthy method
2) To quickly see variable type when variable is in the middle of the code and you are looking at the code or debugging it - and you want to avoid jumping to var section
Feature requests are often about convenience that do not justify implementation. When variable declarations are limited to the declaration section, it gives a good overview plus the compiler doesn't need to worry about additional declarations involving extra stack frames elsewhere in the code. Typically, with iteration variables, programmers find it 'annoying' having to declare such a 'tiny' variable in the declaration section. What's more, with multiple iterations, such variables are declared with each loop, which is not efficient. I sometimes used this feature with languages that support it, but from a user experience it is rather trivial and not worth the overhead it creates nor the effort to implement it IMO.
Title: Re: Question ?!!!!
Post by: BeniBela on April 24, 2020, 01:47:44 pm
The inline for loop declaration would protect one from:

1. using the loop variable before the loop where it is still unitialized

2. using the loop variable after the for loop where is has become uninitlaiized again

3. using a global variable as loop variable




I just cannot use for loops without inline variables (https://github.com/benibela/xidel/commit/e58a28e796e1b962a560ede1d976ee0aea190cb2). Lazarus can automatically declare the variable for the loop? Well, it does not when there is a global variable with the same name
Title: Re: Question ?!!!!
Post by: munair on April 24, 2020, 02:02:43 pm
The inline for loop declaration would protect one from:

1. using the loop variable before the loop where it is still unitialized

2. using the loop variable after the for loop where is has become uninitlaiized again

3. using a global variable as loop variable
Point 1 is not an issue because using the iterator for something else before the loop means it should be regarded as a normal variable (which it is) that might need initialization.

Point 2 depends on compiler policy. For example, I remember from QuickBASIC that if a loop completes, the iterator was always max_iter_value + 1  and when the loop was short-cut, the iterator returned the value of the last iteration. There was never an ambiguous situation.

I do not see the problem with point 3 either. Although I cannot remember ever having used a global variable in a sub-scope as iterator, the state of the variable during and after the loop is the same as any other iterator. Naturally, if the iterator is not declared in the respective scope, the compiler will try to find a match in an encompassing scope or the global scope, but that is entirely the programmer's responsibility. In this respect, good programming practice is key and no compiler can beat that.
Title: Re: Question ?!!!!
Post by: ASerge on April 24, 2020, 02:10:45 pm
However I do think that we are missing some syntax sugar. For example implementing unified try-except-finally block would bring more clarity to complex code since FreePascal does not have garbage collector and we already have to use try-finally block in order to avoid memory leaks and make sure that each object creation always ends with destruction:
Code: Pascal  [Select][+][-]
  1. try
  2.   ..
  3. except
  4.   ..
  5. finally
  6.   ..
  7. end;
I strongly disagree. These are two different expressions. The fact that they are united by the word "try" is not a reason for their combined. Moreover, most likely, you mean (will also have to strain attention) a more frequent option:
Code: Pascal  [Select][+][-]
  1. try
  2.   try
  3.   finally
  4.   end;
  5. except
  6. end;
But in most languages where the construction is combined, the following is assumed:
Code: Pascal  [Select][+][-]
  1. try
  2.   try
  3.   except
  4.   end;
  5. finally
  6. end;
Combining will cause the habit of doing extra initialization of the variable that will be in the finally block, precisely because the blocks are combined and you need to somehow mark the situation when the resource was not allocated. A couple of years ago, here on the forum, I gave the code that investigated the sources of Delphi 7 for try blocks. The vast majority (more than 90%) are try finally blocks. For me, this is normal and for the sake of the remaining percent there is no point in combining.
Title: Re: Question ?!!!!
Post by: 440bx on April 24, 2020, 02:26:00 pm
We can agree that we disagree. I do not have a problem to stay it that way.
I understand and have no problem in agreeing to disagree.

I just want to mention that I did qualify that it is a nice feature when it is not abused/misused.    When abused and/or misused, just like any other feature, it can make things complicated.
Title: Re: Question ?!!!!
Post by: PascalDragon on April 24, 2020, 02:58:53 pm
However I do think that we are missing some syntax sugar. For example implementing unified try-except-finally block would bring more clarity to complex code since FreePascal does not have garbage collector and we already have to use try-finally block in order to avoid memory leaks and make sure that each object creation always ends with destruction:
Code: Pascal  [Select][+][-]
  1. try
  2.   ..
  3. except
  4.   ..
  5. finally
  6.   ..
  7. end;

No, we don't miss that. In most cases you'll have the following scheme:

Code: Pascal  [Select][+][-]
  1. try
  2.   somevar := AcquireResource; // e.g. call a constructer
  3.   try
  4.     DoSomething(somevar);
  5.   finally
  6.     ReleaseResource(somevar); // e.g. Free
  7.   end;
  8. except
  9.   HandleException;
  10. end;

The point here is that you protect the whole handling of the resource including its acquisition with a tryexcept block while only the dealing with the acquired resource is protected by a tryfinally block. This way one does not need to care about the value of somevar. What is suggested with the combined block however is this:

Code: Pascal  [Select][+][-]
  1. try
  2.   try
  3.     somevar := AcquireResource;
  4.     DoSomething(somevar);
  5.   finally
  6.     ReleaseResource(somevar);
  7.   end;
  8. except
  9.   HandleException;
  10. end;

If AcquireResource raises an exception then no value is assigned to somevar so ReleaseResource might work on garbage thus resulting in another crash. This means that you need to manually ensure that somevar is valid (e.g. by doing a somevar := Nil if it's a class instance variable before the tryfinallyexcept block). And no, it does not matter whether the finally is first or the except is first. The initialization is required either way.

We had a thread on one of the mailings lists some years ago where this was discussed till exhaustion (cause someone had suggested this feature again) and we've rejected it back then as well... A pity I can't find that thread anymore...
Title: Re: Question ?!!!!
Post by: Zoran on April 24, 2020, 03:47:40 pm
Inline variables is a nice feature
We can agree that we disagree. I do not have a problem to stay it that way.

Avra, you cut the main part of 440bx's sentence:

Inline variables is a nice feature provided it is well implemented.

Did you read what 440bx actually suggested (see here) (https://forum.lazarus.freepascal.org/index.php/topic,43172.msg323311.html#msg323311)?

That is something quite different from what Delphi introduced. These would be actually "block scope" varables, not "inline" variables. And, unlike Delphi's inline variables, I would like to have it. Declaring a variable in a scope as small as possible is a good practise, at least it is very helpful in debugging.

I fully agree with you that inline variables, implemented as in Deplhi, are a bad feature. Hopefully, FPC will never follow this.
Title: Re: Question ?!!!!
Post by: Thaddy on April 24, 2020, 03:57:37 pm
I fully agree with you that inline variables, implemented as in Deplhi, are a bad feature. Hopefully, FPC will never follow this.
Yes. Again, if only because the separation of declaration and implementation is an essential Pascal feature. Although I am less against type inference inside implementation blocks. That achieves the same but is less error prone.
I'd rather not see it, but e.g. extend the meaning of index to ordinal types for use in loops would not be too intrusive. That can be type inferred.
Code: Pascal  [Select][+][-]
  1. for index := 0 to 9 do; // index is type inferred as a loop variable and index is now an extended language element
Such code would be like declaring i as index variable and then loop. i stands already for index for most programmers.
Problem is nested loops (i,j,k), maybe:
Code: Pascal  [Select][+][-]
  1. for index(0) := 0 to 9 do for index(1) := 10 to 90;//etc
Although this may be solved by the compiler since that knows inner from outer loops..
Code: Pascal  [Select][+][-]
  1. for index := 0 to 9 do for index := 10 to 90;// get the point.
Then again less readable than separation.
OTOH inline variables seem to be mainly used for loops, so what do you think?
Title: Re: Question ?!!!!
Post by: BeniBela on April 24, 2020, 06:10:12 pm
Point 1 is not an issue because using the iterator for something else before the loop means it should be regarded as a normal variable (which it is) that might need initialization.

Point 2 depends on compiler policy. For example, I remember from QuickBASIC that if a loop completes, the iterator was always max_iter_value + 1  and when the loop was short-cut, the iterator returned the value of the last iteration. There was never an ambiguous situation.

I do not see the problem with point 3 either. Although I cannot remember ever having used a global variable in a sub-scope as iterator, the state of the variable during and after the loop is the same as any other iterator. Naturally, if the iterator is not declared in the respective scope, the compiler will try to find a match in an encompassing scope or the global scope, but that is entirely the programmer's responsibility. In this respect, good programming practice is key and no compiler can beat that.

FreePascal just has the worst policy. The variable becomes uninitialized, but fpc often  does not show a warning about it when using uninitialized variables.


The problem with 3 is that two functions can use the same global variable as loop iterator. And when one function calls the other function in the loop, the outer loop might never terminate.

Modern compilers enforce good programming practice.






With inline variables and the new managed records, there would be an alternative to the try..except..finally:


Code: Pascal  [Select][+][-]
  1.     try
  2.       var somevar: SMARTPOINTER := AcquireResource; // e.g. call a constructer
  3.       DoSomething(somevar);
  4.     except
  5.       HandleException;
  6.     end;
  7.  
Title: Re: Question ?!!!!
Post by: Thaddy on April 24, 2020, 06:51:29 pm
Code: Pascal  [Select][+][-]
  1.     try
  2.       var somevar: SMARTPOINTER := AcquireResource; // e.g. call a constructer
  3.       DoSomething(somevar);
  4.     except
  5.       HandleException;
  6.     end;
  7.  
Thanks for ruining my eyesight. Horrible, and against Pascal principles.
Title: Re: Question ?!!!!
Post by: munair on April 24, 2020, 07:08:46 pm
FreePascal just has the worst policy. The variable becomes uninitialized, but fpc often  does not show a warning about it when using uninitialized variables.

Yep, not good.

Quote
The problem with 3 is that two functions can use the same global variable as loop iterator. And when one function calls the other function in the loop, the outer loop might never terminate.

I would always advice against the use of a global variable as iterator in a local loop. Compilers can warn about that or even disallow it. But then it should also check inc/dec of variables inside loops like repeat... and while...
Title: Re: Question ?!!!!
Post by: Thaddy on April 24, 2020, 07:39:45 pm
Or this sidenote:
Code: Pascal  [Select][+][-]
  1. {$mode delphi}{$H+}
  2. var
  3.   i:integer;
  4. begin
  5.   for i := 0 to 10 do
  6.   begin
  7.     writeln(i);
  8.     inc(pinteger(@i)^);
  9.   end;    
  10. end.
It is not only globals....maybe a defined inferred index variable is a good idea after all

(code also works in Delphi)
Title: Re: Question ?!!!!
Post by: munair on April 25, 2020, 08:15:05 am
I haven't checked what code FPC generates with inline variables. However, with for-loops the undefined state of the iterator has a disadvantage. I remember using the iterator - in particular if the loop was shortcut - as flag and also as upper bound index. It would require an additional variable to do the counting if the iterator itself cannot be used afterwards.

Point is, without making things complicated, you keep the natural state. In the following example 'i' returns its natural state after the loop, which is always max_iter + 1 guaranteed and if the loop was short-cut, 'i' returns the number of iterations (i <= max_iter). IOW it doesn't need to be set or adjusted afterwards by the compiler to return that result.
Title: Re: Question ?!!!!
Post by: PascalDragon on April 25, 2020, 03:38:07 pm
FreePascal just has the worst policy. The variable becomes uninitialized, but fpc often  does not show a warning about it when using uninitialized variables.

FPC does warn/hint/note about uninitialized variables. However in case of a for-loop the counter variables becomes undefined (at least if the loop isn't left with a break or goto). I agree however that FPC should warn/hint/note in this case.
Title: Re: Question ?!!!!
Post by: munair on April 28, 2020, 11:53:56 am
A scope has the same characteristics as a function/procedure except it is not callable.
... and doesn't pass parameters.
Title: Re: Question ?!!!!
Post by: 440bx on April 28, 2020, 11:59:59 am
... and doesn't pass parameters.
Correct. :)
Title: Re: Question ?!!!!
Post by: smaniok on June 01, 2020, 07:48:10 am
A scope has the same characteristics as a function/procedure except it is not callable.  It can only be inside a function/procedure.  That is fully consistent with the essence of Pascal and offers some very nice abilities.  For instance...
Code: Pascal  [Select][+][-]
  1. SomeProc(parameters : types, ...);
  2. const
  3.   aconst : 123;
  4. type
  5.   sometype = 1..10;
  6. var
  7.   whatever : sometype;
  8. begin
  9.   statement;
  10.   statement;
  11.   ...
  12.   scope step1;
  13.   { any definitions/declarations within a scope are local to the scope }
  14.     type
  15.       scopetype = sometype;
  16.     const
  17.       scopeconst = 3;
  18.     var
  19.       scopevar : integer;
  20.   begin
  21.     statement;
  22.     statement;
  23.  
  24.     if somecondition then break; { breaks out of the scope - not the function/procedure - just like in a loop }
  25.  
  26.     statement;
  27.     statement;
  28.   end;
  29.  
  30.   scope step2;
  31.   begin
  32.    statement;
  33.    statement;
  34.    ...
  35.   end;
  36. end;
  37.  

Your suggestion for scoped block declaration is more Pascal-like than the Delphi implementation, but in my oppinion it brings too much overload to the language syntax. I think a feature like this is justified only if it brings considerable gains in performance. By the way, would not this syntax cause some confusion with a possible future implementation of anonymous methods? Just saying because it seems similar to Delphi's anonymous methods syntax (of course I don't know if FPC plans to implement the same way), only differs the lack of the procedure keyword, like in this case:

Code: Pascal  [Select][+][-]
  1. procedure TMyClass.DoSomething;
  2. type
  3.   TProc = reference to procedure;
  4. var
  5.   Proc: TProc;
  6. begin
  7.   Proc := procedure
  8.   var
  9.     a: string;
  10.   begin
  11.     a := 'Hello';
  12.     ShowMessage(a);
  13.   end;
  14.   Proc;
  15. end;
  16.  

But getting back to the subject, I am not totally against the Delphi way of implementing inline variables.

So, var section must be just above begin keyword. Then varible has block-scope.
Then, these are truly block-scope variables, not just "inline variables", that Emarcadero introcuded.

Delphi actually allows scoping inline variables if you put then INSIDE a nested begin..end block. Type inference makes some assignments a little less redundant to write and adds simplicity to the code. The only negative point I see is the syntax that not follows the original Pascal concepts of declaring everything BEFORE the begin..end;

However, I wish I could declare a variable in a loop like this in FPC:
Code: Pascal  [Select][+][-]
  1. for var i := 1 to 5 do
  2.  
but I understand that if it costs turning the language into a Frankenstein, with various pieces without consistency, I prefer FPC stays the way it is.
Title: Re: Question ?!!!!
Post by: Thaddy on June 01, 2020, 10:32:53 am
hence I suggested for the latter example to create index as a keyword. The compiler can know that an index variable is required, even nested, and the ugly var is gone.
Code: Pascal  [Select][+][-]
  1. // in this case suppose index is a keyword, requesting the compiler to create it
  2. for index := 0 to 4 do
  3.   for index := 3 to 7 do;
  4.  
Effect is the same, but I believe the syntax is a lot cleaner..
Other example I thought of is to extend for to forindex, like:
Code: Pascal  [Select][+][-]
  1.  
  2. // this assumes forindex is a new keyword in the for family
  3. forindex :=0 to 4 do
  4.   forindex := 3 to 7 do;

And I also thought of simply:
Code: Pascal  [Select][+][-]
  1. for 0 to 4 do
  2.   for 3 to 7 do;
All are to simplify for loop syntax. All are possible. All are things that are not necessary, but at least they are more natural.
Title: Re: Question ?!!!!
Post by: 440bx on June 01, 2020, 12:21:51 pm
in my oppinion it brings too much overload to the language syntax.
On the contrary, unlike inline variables it does not overload the "begin" and "end" keywords as block delimiters.

I think a feature like this is justified only if it brings considerable gains in performance.
That feature has nothing to do with performance.  It wouldn't affect performance one way or the other.  What that feature is about is localizing constant, type and variable definitions within a function/procedure.  That means, instead of potentially having a significant number of locals, which turn out to be globals within the function/procedure/method, it would allow a much smaller number of locals because "throw away temporary variables" would be confined to the scope.  That would make the code easier to understand and maintain.

By the way, would not this syntax cause some confusion with a possible future implementation of anonymous methods?
It shouldn't.  Inline scopes should always be identified by a keyword to indicate their presence.


Delphi actually allows scoping inline variables if you put then INSIDE a nested begin..end block.
THAT is syntax overloading.  "begin"/"end" are very poor block delimiters.  The reason is, in a Pascal block, the programmer is supposed to be able to declare constants and types but, apparently these block features would not be available by overloading "begin"/"end".  Overloading "begin"/"end" as block delimiters is just a hack.  Another "writable constants" bright idea.

Type inference makes some assignments a little less redundant to write and adds simplicity to the code. The only negative point I see is the syntax that not follows the original Pascal concepts of declaring everything BEFORE the begin..end;
That's not the only potential problem with type inference.  Pascal's strong type checking depends on explicit type declarations, type inference has the potential to create situations where the compiler would infer a type that is not the one the programmer had in mind.

However, I wish I could declare a variable in a loop like this in FPC:
Code: Pascal  [Select][+][-]
  1. for var i := 1 to 5 do
  2.  
With inline scopes you can do that and then some, all without altering the way variables are declared.

but I understand that if it costs turning the language into a Frankenstein, with various pieces without consistency, I prefer FPC stays the way it is.
Too late for that.  If memory serves, writable constants were the first "Frankengimmick" that Borland put into Pascal and, unfortunately, far from the last one.

Fortunately, or maybe unfortunately, it's quite likely that the probability of seeing the Pope named the sexiest male on earth is likely greater than seeing inline scopes implemented in FPC.



hence I suggested for the latter example to create index as a keyword. The compiler can know that an index variable is required, even nested, and the ugly var is gone.
Code: Pascal  [Select][+][-]
  1. // in this case suppose index is a keyword, requesting the compiler to create it
  2. for index := 0 to 4 do
  3.   for index := 3 to 7 do;
  4.  
Effect is the same, but I believe the syntax is a lot cleaner..
And how would a two dimensional array "A" element be addressed ?... A[index, index] ? being able to address only the elements on the diagonals of square arrays doesn't seem to be a very useful "feature".

As far as controlling repetitions, that nested loop is basically a convoluted way of writing "for i := 1 to 25 do ;"  The other examples you showed have the same problems.

Title: Re: Question ?!!!!
Post by: Thaddy on June 01, 2020, 01:03:28 pm
They are not really problems for the compiler side. But as I stated many times that I find it important that declaration and implementation are separated. Such constructs as I presented are cleaner though, because of inference and there is less wrong with that.
I'd rather see only inference for those kind of instructions than explicit declarations in an implementation part: that is NOT Pascal.
IF such things are implemented, try to keep the separation, is more or less my way of thinking.
Many C and C++ programmers agree, btw, - e.g. Linus Torvalds - inline declarations are evil. Perhaps apart from loop variables as intrinsic.
Not from a point of convenience, but from a point of maintainability and team work.
People tend to focus on convenience..., which is wrong for large code bases.
Title: Re: Question ?!!!!
Post by: Warfley on June 02, 2020, 03:53:56 pm
In my opinion there is (at least in pascal) only one argument in favor of inline variable declaration, which is scoping.

When using scoped variables you can have different types for the same variable name, not access variables outside their scope (i.e. you know exactly where each variable belongs) and managed variables would only be initialized when the scope is entered (i.e. on an if, only if that branch is taken) and destroyed when the scope is left (which could lead to better performance and a fine grade of control over how and when memory is used e.g. by arrays).

That said all of these points are not really strong arguments because:
1. using same name for different types means you name is meaningless, this is more a symptom of bad naming
2. If you have to many scopes so you loose track of your variables, probably your function is to big and you should outsource some scopes to (nested) functions
3. If you need the performance of managed types, you can still call finalize and initialize by hand for memory areas, or use functions (which through inlining most certainly will not add overhead). And for the memory usage, one can always free managed types, e.g. Strings or Arrays by setting them to nil

So In a clean code base I don't see any reason why this would be required. Things like being able to use the same name for different types makes the code even worse in my opinion. The only thing where I can see real advantages imho is the for and for-in loops. While looping variables should be recognizable by their naming, I've already had this code:
Code: Pascal  [Select][+][-]
  1. for i:=0 to len -1 do
  2.   foo(i);
  3.   bar(i);
Where I forgott the begin/end (because it was a oneliner at first and then I've added more lines), and in this cases a compiler error that I'm accessing the loop variable outside it's scope would be nice
Title: Re: Question ?!!!!
Post by: Thaddy on June 02, 2020, 04:04:25 pm
That last part is python syntax... by indentation...
Title: Re: Question ?!!!!
Post by: Warfley on June 02, 2020, 04:23:48 pm
That last part is python syntax... by indentation...
Yes, but my point was that I've already had the situation that I brainlessly added a line line to a for loop, but because it was previously a one liner, I had no begin-end and  therefore the next line was not part of the for loop.

I now try to use begin-end everywhere (except where it will only be one liners like raising errors or calling exit/break/continue), but in such a case a warning (or compilation error) by the compiler would have been nice. Or in general, if you use a loop variable after the loop
Title: Re: Question ?!!!!
Post by: PascalDragon on June 03, 2020, 09:28:58 am
So In a clean code base I don't see any reason why this would be required. Things like being able to use the same name for different types makes the code even worse in my opinion. The only thing where I can see real advantages imho is the for and for-in loops. While looping variables should be recognizable by their naming, I've already had this code:
Code: Pascal  [Select][+][-]
  1. for i:=0 to len -1 do
  2.   foo(i);
  3.   bar(i);
Where I forgott the begin/end (because it was a oneliner at first and then I've added more lines), and in this cases a compiler error that I'm accessing the loop variable outside it's scope would be nice

Optimally the compiler would warn you that i in the call to bar is undefined. At least with -O3 in trunk (don't know if in 3.2.0 as well) it already does:

Code: Pascal  [Select][+][-]
  1. program tforvar;
  2.  
  3. procedure Foo(aArg: LongInt);
  4. begin
  5.  
  6. end;
  7.  
  8. procedure Test;
  9. var
  10.   i: LongInt;
  11. begin
  12.   for i := 0 to 20 do
  13.     Foo(i);
  14.   Foo(i);
  15. end;
  16.  
  17. begin
  18.   Test;
  19. end.

Code: [Select]
PS E:\fpc\git> .\compiler\ppc386.exe -n -Furtl\units\i386-win32 -viwnh -FEtestoutput -O3 .\fpctests\tforvar.pp
Target OS: Win32 for i386
Compiling .\fpctests\tforvar.pp
tforvar.pp(3,15) Hint: Parameter "aArg" not used
tforvar.pp(14,8) Warning: Local variable "i" does not seem to be initialized
Linking testoutput\tforvar.exe
19 lines compiled, 0.0 sec, 29120 bytes code, 1316 bytes data
1 warning(s) issued
1 hint(s) issued

It's a work in progress however.
Title: Re: Question ?!!!!
Post by: 440bx on June 03, 2020, 09:44:45 am
It's a work in progress however.
Nice that the compiler is keeping track of "no initialization" across "for" loops.
Title: Re: Question ?!!!!
Post by: Thaddy on June 03, 2020, 10:01:02 am
Really nice, given -Sew : treat warnings as errors (which the compiler demands from compiling itself!)
Title: Re: Question ?!!!!
Post by: Blade on April 08, 2021, 05:50:46 pm
They are not really problems for the compiler side. But as I stated many times that I find it important that declaration and implementation are separated. Such constructs as I presented are cleaner though, because of inference and there is less wrong with that.
I'd rather see only inference for those kind of instructions than explicit declarations in an implementation part: that is NOT Pascal.
IF such things are implemented, try to keep the separation, is more or less my way of thinking.
Many C and C++ programmers agree, btw, - e.g. Linus Torvalds - inline declarations are evil. Perhaps apart from loop variables as intrinsic.
Not from a point of convenience, but from a point of maintainability and team work.
People tend to focus on convenience..., which is wrong for large code bases.

I agree with this, and such things as greater code readability and maintainability should not be taken lightly.  Looking at many of the attacks and criticisms of the Pascal language, a significant category of such is that Pascal is different from C-family languages.  It's amazing to see some from C/C++/C# get all hot and bothered simply by Pascal's "with", "begin", or "end". 

Taking a moment to declare variables and functions, or to think about their purpose and necessity can be asking too much.  Code fast and impatiently at the start, worry about the problems and ramifications later, sneak off into the night before the titanic sinks, pass the buck on to the next programmer to maintain a disaster, and/or flip off disappointed customers/users/companies.

If you read various forums on the web, the antagonism against non C-family languages and syntax appears to go back to the 1970s, and has been instilled into the culture.  Pascal is a particular focus point for it, which is partially why some such people have been gleefully claiming that somehow it's dead/wishing for its death (or hoping to remove non C-family alternatives) for over the past 20 years.  So I can only imagine what goes through the minds of C++ advocates at Embarcadero.  "Why not make Pascal just another flavor of C/C++?"

Additionally, Embarcadero is about IDE/compiler sales, not what is the best design or in the best interest of the Pascal language.  Whatever is a neat trick or fad can be on the table, not producing higher quality programmers nor good programming practices.  If they think creating havoc with "Frankenstein Pascal" might just slightly bump the sales needle by removing "with", turning "begin/end" to "{ }", and removing "declarations" and "implementation" all together then their management might give it a try.  Then if there is nothing left but C++ Builder, after having torpedoed and destroyed Delphi with incompetence, they then may give C# Builder another shot or for a quick buck introduce an unasked for Python Builder.
Title: Re: Question ?!!!!
Post by: OwlOfTime on April 08, 2021, 07:05:41 pm
Just a quick question to don't read all the pages. What is the current state of this?

In mode Delphi should be supported or that is not important anymore?
Title: Re: Question ?!!!!
Post by: Bart on April 08, 2021, 07:24:21 pm
AFAIK the fpc team is NOT going to implement this, regardless of language mode.

Bart
Title: Re: Question ?!!!!
Post by: marcov on April 08, 2021, 08:32:10 pm
AFAIK the fpc team is NOT going to implement this, regardless of language mode.

Afaik it was more diplomatic and more along the lines of "not in the coming 5 years, never say never".
Title: Re: Question ?!!!!
Post by: Thaddy on April 08, 2021, 08:49:51 pm
I got some private response regarding type inference for loops, though.
In general inline declarations are evil imho.
Title: Re: Question ?!!!!
Post by: MarkMLl on April 08, 2021, 09:28:10 pm
AFAIK the fpc team is NOT going to implement this, regardless of language mode.

Afaik it was more diplomatic and more along the lines of "not in the coming 5 years, never say never".

Trying to be diplomatic, that's not really the impression that many if not most of the rest of us have of this long-term debate.

"You are not the first with such suggestions and you're also not the first we're shooting down, because there simply will not be any modifications added to the compiler that changes syntax/language fundamentals." -- https://forum.lazarus.freepascal.org/index.php/topic,53721.msg397816.html#msg397816

My own take on it is that a local variable declared in a "for" clause is less evil than the current situation where the index variable is still in scope but has an undefined value upon exit from the controlled statement.

The bottom line is that if we don't like it, we're at liberty to fork the compiler... which is a viable option for those of us using it for business purposes, who have little incentive to worry about putting code on Github etc. where it would be incompatible with the mainstream.

My own preference would be to migrate to an ALGOL-based language which is extensible in a controlled fashion, and if this had been designed with reasonable input from the C/C++ community it would almost certainly allow local declarations. However I don't relish losing the mature FPC/Lazarus libraries: to that extent the developers have the users over a barrel and I sincerely hope that they're never caught gloating over it.

MarkMLl
Title: Re: Question ?!!!!
Post by: marcov on April 08, 2021, 09:46:29 pm
However I don't relish losing the mature FPC/Lazarus libraries: to that extent the developers have the users over a barrel and I sincerely hope that they're never caught gloating over it.

There is no barrel. It is a new feature. Just don't start using it on the Delphi side and you are fine. Most 3rd party libraries/components won't anyway because of compatibility with older Delphis.

And no, gloating is not a worth of it. Intense regret over wasted time discussing bullshit features is more like it.



Title: Re: Question ?!!!!
Post by: PascalDragon on April 09, 2021, 02:23:54 pm
AFAIK the fpc team is NOT going to implement this, regardless of language mode.

Afaik it was more diplomatic and more along the lines of "not in the coming 5 years, never say never".

Trying to be diplomatic, that's not really the impression that many if not most of the rest of us have of this long-term debate.

For this specific feature that is indeed the impression I personally am shooting for. I won't implement it and I also won't integrate any patch that implements this feature, because I don't support this functionality. I can't and don't speak for the other core devs however.
Title: Re: Question ?!!!!
Post by: munair on April 10, 2021, 10:35:08 am
I got some private response regarding type inference for loops, though.
In general inline declarations are evil imho.

I couldn't agree more.

My own take on it is that a local variable declared in a "for" clause is less evil than the current situation where the index variable is still in scope but has an undefined value upon exit from the controlled statement.

Declaring variables in and implicitly limiting them to the "scope" of a for-loop or other control block as various languages support is bad language design. The only clean way to implement this is by allowing explicit scope-block definitions, but for some well-defined and established languages even that wouldn't be an option as it could easily mess up existing scope rules.

An undefined iterator after a loop should not be an issue as the very purpose of its existence is iteration only.

Don't blame a well thought-through language design for bad programming behaviour.
TinyPortal © 2005-2018