Recent

Author Topic: Question ?!!!!  (Read 4872 times)

SymbolicFrank

  • Hero Member
  • *****
  • Posts: 635
Re: Question ?!!!!
« Reply #30 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.

Thaddy

  • Hero Member
  • *****
  • Posts: 9184
Re: Question ?!!!!
« Reply #31 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.
« Last Edit: June 10, 2019, 06:09:58 pm by Thaddy »
also related to equus asinus.

SymbolicFrank

  • Hero Member
  • *****
  • Posts: 635
Re: Question ?!!!!
« Reply #32 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!".

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 7504
Re: Question ?!!!!
« Reply #33 on: June 10, 2019, 06:02:37 pm »
If documented, it is of course ok.

440bx

  • Hero Member
  • *****
  • Posts: 1199
Re: Question ?!!!!
« Reply #34 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.







using FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

SymbolicFrank

  • Hero Member
  • *****
  • Posts: 635
Re: Question ?!!!!
« Reply #35 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.

Zoran

  • Hero Member
  • *****
  • Posts: 1464
    • http://wiki.lazarus.freepascal.org/User:Zoran
Re: Question ?!!!!
« Reply #36 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.


Thaddy

  • Hero Member
  • *****
  • Posts: 9184
Re: Question ?!!!!
« Reply #37 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.
« Last Edit: June 11, 2019, 11:54:37 am by Thaddy »
also related to equus asinus.