Lazarus

Miscellaneous => Suggestions => Topic started by: AlanTheBeast on January 07, 2016, 08:50:50 pm

Title: Ada style "for" loop counters
Post by: AlanTheBeast on January 07, 2016, 08:50:50 pm
I'd like to suggest an addition to fpc's "Pascal" definition:

         that for loop indexes could be like those in Ada - that is, do not require a
         variable declaration. They would always be word/integer (longword/longint/
         Qword/int64) as needed and would only "exist" within the for loop block.

(Ada is much more strict on typing than Pascal, yet it allows simple loop control w/o declaring the variable).

(* ---------------------------------------------------------------------------------------- *)
Procedure foobar;
var
        p, q: word;
begin

       for i := 1 to 22 do
          begin                          // variable i (word) exists only between here <<<
               p := i * 2;
               foo (p);
               bar (i);
          end;                            //                   and here<<<

       q := 23 + p + i;     // compiler error:  Error: Identifier not found "i"
       writeln (q);

       for i := -3000000 to 0 do bigfoo (i);      // variable i is a longint this time.

end;
(* ---------------------------------------------------------------------------------------- *)

1) i would not need to be declared.
2) i would be a "word" the first time and a longint the 2nd time.
3) i would only exist within the for statement (including within its begin/end block)
4) thus, above a compile time error would not allow the q := operation (above) as i would be
    unknown.

Optionally, programmer ordinal types could be used ( for f := apple to kiwi do  ...) w/o declaring f (assumes the programmer has defined a type that contains those fruit ..).

Note that such a change has no impact on any existing code but would make future coding less work  (not a lot less, but ....)
Title: Re: Ada style "for" loop counters
Post by: BeniBela on January 07, 2016, 08:59:55 pm
+1


(I might  suggested this a dozen times by now)
Title: Re: Ada style "for" loop counters
Post by: molly on January 07, 2016, 09:07:53 pm
--1000%
Title: Re: Ada style "for" loop counters
Post by: eny on January 07, 2016, 09:15:48 pm
WTH is this? Global FPC bashing year???

http://forum.lazarus.freepascal.org/index.php/topic,30967.msg197511.html#msg197511
Title: Re: Ada style "for" loop counters
Post by: molly on January 07, 2016, 09:21:29 pm
@eny
And don't forget the curly braces thread in day 3 of this year.

People who keep insisting on introducing such non-sense clearly have no idea about the origin and idea's behind pascal programming language.

Such features adds complexity, introduces inconsistency and is plain ugly to debug. On the fly-untyped variables... *barf*
Title: Re: Ada style "for" loop counters
Post by: marcov on January 07, 2016, 10:05:51 pm
Then please all reply with

first check

http://www.freepascal.org/faq.var#extensionselect

before suggesting language features


In this case just change warnings to errors, and you have  the safety part:

Quote
  -Se<x>     Error options. <x> is a combination of the following:
         <n> : Compiler halts after the <n> errors (default is 1)
         w : Compiler also halts after warnings
         n : Compiler also halts after notes
         h : Compiler also halts after hints

Non declaration is shorthand, and the extension faq covers that.
Title: Re: Ada style "for" loop counters
Post by: AlanTheBeast on January 07, 2016, 10:39:20 pm

People who keep insisting on introducing such non-sense clearly have no idea about the origin and idea's behind pascal programming language.

Such features adds complexity, introduces inconsistency and is plain ugly to debug. On the fly-untyped variables... *barf*

I likely have more insight than most into what Mr. Wirth meant by his prototype of Pascal.  Indeed he didn't like it enough and went on to new things such as Modula II (which inspired a lot of new features in Pascal as seen in TP from about 4.0 onward [as well as other compilers]).  Pascal today is not what Mr. Wirth envisioned at the start but then many things are not.

Ada's type strictness was in large part inspired by Pascal - for very good reason.  Further, it is MUCH MORE TYPE STRICT than Pascal.

And yet, for the simple purpose of loop control, no strict declaration of for loop control variables is required in Ada (it is, of course, allowed).  This is why I proposed it here.

It is not complexity - it is simplicity.  I'd venture that 90% or more of my loop control variables are named i,j,k,m,n,p,q (in about that order) and that 90% of them, further, are used for 15 lines of code, or less (maybe more if nested deep enough).  They are ephemeral by their nature.

Such are certainly well taken care of when debugging Ada programs.

Finally, Pascal now allows the abomination of C operations like       a+ = c      albeit permitted by compiler directive (relief - may it never see my machine).

Now that is awful.  Stupid.  Insane bad style.  Just as bad as curly braces.  Of course that's not at all what I've suggested.

What I suggest is very natural however.  In context, any programmer can see that a for loop needs an index.  Needing to declare a type for it is quite redundant.  Using the correct type for it is something the compiler can divine easily enough from the range or type of the begin/end values of the loop.

Further, it lends itself very well to register optimization of loop control variables.  (May be redundant).

Finally, it was a suggestion.  It certainly doesn't merit the ridicule you heap on it via a ridiculous comparison with a ridiculous idea from someone else.

Suggestions should be discussed - not dismissed out of hand because they fail your particular purity test.

Title: Re: Ada style "for" loop counters
Post by: AlanTheBeast on January 07, 2016, 11:44:45 pm

first check

http://www.freepascal.org/faq.var#extensionselect

before suggesting language features[/b][/size]

In this case just change warnings to errors, and you have  the safety part:

Quote
  -Se<x>     Error options. <x> is a combination of the following:
         <n> : Compiler halts after the <n> errors (default is 1)
         w : Compiler also halts after warnings
         n : Compiler also halts after notes
         h : Compiler also halts after hints

Non declaration is shorthand, and the extension faq covers that.

Not sure why you believe massive fonts make your reply better.

As to the provided link.  The first point says:
Compatibility must not be compromised in any way. Existing codebases on at least the Pascal level must keep running. This is often more difficult than most people think.

My suggestion does not invalidate a single line of Pascal ever written in the history of Pascal anywhere.  (ie: Declared variables used in for loops would still exist, compile and function).

The next point says:
The extension must have real value. Anything that is only a shorter notation does not apply, unless it is out of compatibility with an existing Pascal/Delphi codebase. Practically it means it must make something possible that cannot be done otherwise or be a compatibility item

My suggestion does not invalidate that notion at all except that it eliminates the _formal_ declaration of loop control variables.  Of course it would only apply to the fpc compiler versions that incorporate it and therefore to IDE's that use those fpc's.  Some editors/IDE's may flag it.  It could be directive flagged on/off in case there are SQA objections (just as the unholy abomination of C operators (    a+ = c    )).

Then it goes onto:
The change must fit in with the scope of the project: implementing a Pascal compiler with support for RAD and a generic DB system. This excludes features like inline SQL, and large garbage collected object frameworks.

The change is too local in scope (within a line of code or the begin .. end scope it controls).  This should have 0 impact on any DB system, garbage collection, SQL, objects, etc.  As to RAD ... well, it should be obvious that it only helps one to write control loops w/o the maintenance of control loop variables whose types can easily be inferred from the loop control constants or variable type(s).

As to the rest, the desirability for such is obvious (at least to me) - it simplifies and accelerates coding and is a well proven language feature of the most safety/mission-critical oriented language that there ever has been (Ada).  The programmer doesn't have to focus on writing formal declarations (and fixing errors) for one of the most fundamentally used features of most programming languages.  Indeed: because the type of the variable is guaranteed by the compiler to be correct for the type of the begin/end constants or variables of the loop there will be fewer errors in the generated op code due to programmer error - this is most especially valid over the life cycle of the code as things change and perhaps attention is not paid in change to the type declaration of the control variable.

Importantly to READABILITY of the code:   It simplifies and clarifies coding because the VAR block of a procedure or function can be constrained to declare and describe the more critical/important variables and leave implicit the simple things that control for loops.  Further, although this is covered by compiler optimization, it removes to the bottom of the stack those control variables making word/longword alignment simpler.  Also these variables need not even be on the stack at all if they can be done in register (again, perhaps best left to the optimization code).

The compiler can assign symbols that can be used by the debugger.  If a variable name is used for separate control blocks - and has different types then the compiler can name them sequentially within the procedure or function appropriately  (_U_$P$LOCI_$$_I_1, _U_$P$LOCI_$$_I_2 ...).

The test cases are pretty simple.  Put like named variables in the global section of programs/units; passed parameters; and local variables with incompatible types to the for loop.  The compiler should warn or stop appropriately.

"A design is not complete when there is nothing to add, it is complete when there is nothing left to take away."
 -Le Courbousier.
Title: Re: Ada style "for" loop counters
Post by: molly on January 08, 2016, 12:25:50 am
First of all let me apologize for my initial rude response. For me it was a drop that pushes the water out of the bucket, as also indicated by eny.

Although i'm fairly new as in having an account over here, i watch these forums for quite some time now, and believe it or not the proposal of wanting to introduce on the fly or scoped variables is a topic that passes here on the forums as well as on mailing list every couple of months.

It is of course more than allowed to express your wishes, wanting to introduce new features trying to convince others, work on and discuss proposals etc.

I agree that over time Pascal evolved, and indeed not all for the better or what N.W. envisioned. Do keep in mind though that some of the introduced features are part of maintaining compatibility with Delphi.

It is not complexity - it is simplicity.  I'd venture that 90% or more of my loop control variables are named i,j,k,m,n,p,q (in about that order) and that 90% of them, further, are used for 15 lines of code, or less (maybe more if nested deep enough).  They are ephemeral by their nature.
Of course they are ephemeral by their nature. But really, in all those discussion i have seen and what i miss in your arguments as well, what on earth is the benefit of having scoped variables (let alone having them as untyped ones).

Quote
What I suggest is very natural however.  In context, any programmer can see that a for loop needs an index.  Needing to declare a type for it is quite redundant.  Using the correct type for it is something the compiler can divine easily enough from the range or type of the begin/end values of the loop.
That we as humans/programmer see this as natural, i will not disagree with.

However, having untyped variables is in my opinion very unnatural for the Pascal language, and adds complexity to the parser/compiler, while the benefits are next to none.

Maybe it is a personal taste of reading sources, but when i dive into c code i am always amazed how some people are able to actually read and understand the code they've written when scoped variables are used and abused all over the place.

Right now things are pretty much clear, as you declare a variable and its type. And even though you can use and abuse that variable to your likings, you will never have to ask yourself, was that variable a byte, an integer, a char, or no the last iteration it went through made it a real (with all the consequences that comes along with that, especially with a typed language). I truly do not understand how they managed to justify this to allow in ADA.
Title: Re: Ada style "for" loop counters
Post by: AlanTheBeast on January 08, 2016, 12:50:33 am

Although i'm fairly new as in having an account over here, i watch these forums for quite some time now, and believe it or not the proposal of wanting to introduce on the fly or scoped variables is a topic that passes here on the forums as well as on mailing list every couple of months.


It is of course more than allowed to express your wishes, wanting to introduce new features trying to convince others, work on and discuss proposals etc.

I agree that over time Pascal evolved, and indeed not all for the better or what N.W. envisioned. Do keep in mind though that some of the introduced features are part of maintaining compatibility with Delphi.

It is not complexity - it is simplicity.  I'd venture that 90% or more of my loop control variables are named i,j,k,m,n,p,q (in about that order) and that 90% of them, further, are used for 15 lines of code, or less (maybe more if nested deep enough).  They are ephemeral by their nature.
Of course they are ephemeral by their nature. But really, in all those discussion i have seen and what i miss in your arguments as well, what on earth is the benefit of having scoped variables (let alone having them as untyped ones).

Quote
What I suggest is very natural however.  In context, any programmer can see that a for loop needs an index.  Needing to declare a type for it is quite redundant.  Using the correct type for it is something the compiler can divine easily enough from the range or type of the begin/end values of the loop.
That we as humans/programmer see this as natural, i will not disagree with.

However, having untyped variables is in my opinion very unnatural for the Pascal language, and adds complexity to the parser/compiler, while the benefits are next to none.

Maybe it is a personal taste of reading sources, but when i dive into c code i am always amazed how some people are able to actually read and understand the code they've written when scoped variables are used and abused all over the place.

Right now things are pretty much clear, as you declare a variable and its type. And even though you can use and abuse that variable to your likings, you will never have to ask yourself, was that variable a byte, an integer, a char, or no the last iteration it went through made it a real (with all the consequences that comes along with that, especially with a typed language). I truly do not understand how they managed to justify this to allow in ADA.


First off thanks for taking the time for a more considered reply.

My suggestion was not on the fly.  I recognized back in about 1990 (when I took an Ada programming course) that implicit control variables was not only a reduction in un-needed formalism (in the most formal of languages of the day), but that it would also contribute to fewer errors in Pascal were it implemented.

I am not suggesting that the control variable in a loop be untyped.  I am suggesting that the type be correctly determined by the compiler according to the constants or variables (or both) that indicate the begin/end of the loop.  As such errors in control loop variable type will be eliminated or inconsistencies in the begin v. end controls of the loop detected and flagged by the compiler (fatal).

Therefore I disagree entirely that there are no benefits:   quicker coding and less "noise" in the VAR section of procedures (no clutter from the added lists of needed control variables).  Again: the "type" of the variable would be strongly set by the compiler.  It is not weak.  Indeed: over the life cycle of the code if those beginning and ending points of the for loop are changed to require a larger type then it would be taken care of automatically and possibly (probably(?)) prevent run time bugs.

What it does for clarity I've put in my more detailed reply to marcov.

Why was it justified in Ada?  Because the compiler imposes simple and clear rules about what that control variable can be.  Indeed, the programmer benefits from the safety of the compiler imposing the correct variable type on the loop.  What I am suggesting is no different.

Note that the new C derived language Swift 2 (from Apple) does things in a similar fashion though I confess I haven't dug into it enough to know how/what it does in this respect.  Apple claim strong safety.

I don't know why you bring up C.  It is an abomination.  It is shit.  Sorry - I prefer shit over C.  I don't know why the c operators (styled   a+ = c,  etc.) were permitted into fpc (I can guess to make importing code easier (?)).  But of course my suggestion has nothing to do with C.  It has to do with syntax from Ada - a most deliberately (the most?) designed programming language.
Title: Re: Ada style "for" loop counters
Post by: x2nie on January 08, 2016, 03:40:38 am
...
(* ---------------------------------------------------------------------------------------- *)
Procedure foobar;
var
        p, q: word;
begin

       for i := 1 to 22 do
          begin                          // variable i (word) exists only between here <<<
               p := i * 2;
               foo (p);
               bar (i);
          end;                            //                   and here<<<

//....

       for i := -3000000 to 0 do bigfoo (i);      // variable i is a longint this time.

end;
(* ---------------------------------------------------------------------------------------- *)

1) i would not need to be declared.
2) i would be a "word" the first time and a longint the 2nd time.
3) i would only exist within the for statement (including within its begin/end block)
..

Note that such a change has no impact on any existing code but would make future coding less work  (not a lot less, but ....)
I think it shall be SynEditor-Autocomplete's job. Or be CodeTool's job.


Didn't we know?, that pressing Ctrl+Shift+C will automagically write the property getter/setter into "private" class block.
plus write getter/setter methods in "implementation" block too?
So, (no matter AutoComplete or CodeTool) must be easy to able to write "var i : longint" into correct place within the procedure, somehow .
Title: Re: Ada style "for" loop counters
Post by: Amir61 on January 08, 2016, 04:11:42 am
I like the idea.

The x2nie's suggestion does not resolve the issue!
Some variables do not deserve to be in the VAR list! They just increase the line of code and make the code less readable.

What I am not sure is why one should stop with just the loop variables: Why should not Pascal allow all the variables to be like this?  Essentially it is like the "auto" type in C++.

As I said, I like the idea but I think it needs a deep understanding of its consequences.
 
Title: Re: Ada style "for" loop counters
Post by: x2nie on January 08, 2016, 04:32:51 am
I like the idea.

The x2nie's suggestion does not resolve the issue!
Some variables do not deserve to be in the VAR list! They just increase the line of code and make the code less readable.

What I am not sure is why one should stop with just the loop variables: Why should not Pascal allow all the variables to be like this?  Essentially it is like the "auto" type in C++.
Well, there is no such things as bad idea. I respect to the any new idea.
But, if were fpc allowing a variable used without declaring the exact type, it should be in new compiler mode. 
such {$mode AlanTheBest} ,eh?
Even fpc will support this new feature, I will disabled that in my local machine very quickly.


I myself will thankful if I always noticed of "mistake" of undeclared variable. Sure, writing  var i : longint still disturbing me. But it just what I really need.





Anyway, my suggestion is based on what AlanTheBeast described by himself in first post:
Quote
Note that such a change has no impact on any existing code but would make future coding less work
So, if you want to code faster less work, let the SynEdit do that (by using autocomplete / codetool?)



Quote from: AlanTheBest
Finally, Pascal now allows the abomination of C operations like       a+ = c      albeit permitted by compiler directive (relief - may it never see my machine).

Now that is awful.  Stupid.  Insane bad style.  Just as bad as curly braces.  Of course that's not at all what I've suggested.
I didn't know when fpc allow a+=c,
but if fpc did, the variables still must be declared in exact type, aren't they?


@AlanTheBest: if you really dislike to declare variable (is it the stupid awful?), use python!
No, do't be offended. Just maybe the best you can get: never typed-variable at all. it help you less work.
Title: Re: Ada style "for" loop counters
Post by: Edson on January 08, 2016, 04:50:27 am
I'd like to suggest an addition to fpc's "Pascal" definition:

         that for loop indexes could be like those in Ada - that is, do not require a
         variable declaration. They would always be word/integer (longword/longint/
         Qword/int64) as needed and would only "exist" within the for loop block.

I think suggestions are welcome. It means there are interest in improving this old language. I love Pascal, like it's, but I thik it could be better.  :)

What it surprise me, is the bad behavior some people here respond when they hear about a language suggestion. %)

Anyway this is just my humble opinion.
Title: Re: Ada style "for" loop counters
Post by: x2nie on January 08, 2016, 04:59:21 am
+2 for Edson. (double thumbs).
You got very good point of view


But about people respons, there are people that have limited english vocabulary (like me).
THere is some difficult to picks english words to express the my mind.
if so, just forget and go forward 8-)
Title: Re: Ada style "for" loop counters
Post by: Leledumbo on January 08, 2016, 05:25:30 am
Feel free to talk and suggest whatever you have, but it would never be in the compiler unless someone wants to implement and maintain it and the dev team accepts the patch. The C-like operator was a legacy extension and the only one I consider as "mistake", but existing code might have used it already, hence it can't be removed. I always disable that though, thanks to the controllability through compiler option.
Title: Re: Ada style "for" loop counters
Post by: marcov on January 08, 2016, 09:56:06 am

Not sure why you believe massive fonts make your reply better.

You noticed, didn't you ?  :)

Quote
The next point says:
The extension must have real value. Anything that is only a shorter notation does not apply, unless it is out of compatibility with an existing Pascal/Delphi codebase. Practically it means it must make something possible that cannot be done otherwise or be a compatibility item

My suggestion does not invalidate that notion at all except that it eliminates the _formal_ declaration of loop control variables.

Well, the netto result vs turning the current warning into an error is shorthand, so I think it does. 

But actually a quote the FAQ more because of the second part, making a complete proposal (e.g. you don't say anything about defining the loopvar type) making a decent plan and find implementation resources etc.

Suggestions are pretty pointless without.

Quote
Of course it would only apply to the fpc compiler versions that incorporate it and therefore to IDE's that use those fpc's.  Some editors/IDE's may flag it.  It could be directive flagged on/off in case there are SQA objections (just as the unholy abomination of C operators (    a+ = c    )).

For the record, I didn't like them when they were implemented, and still don't. But they originate before 2000, multi arch and current extension policies.

Quote
Yes, a
Then it goes onto:
The change must fit in with the scope of the project: implementing a Pascal compiler with support for RAD and a generic DB system. This excludes features like inline SQL, and large garbage collected object frameworks.

(and IMHO implicit inline declarations are not Pascal)

Quote
As to the rest, the desirability for such is obvious (at least to me) - it simplifies and accelerates coding and is a well proven language feature of the most safety/mission-critical oriented language that there ever has been (Ada). 

I don't put Ada on a pedestal. It went too far IMHO. Maybe it achieved its purposes for certain highly specialized industry (like defense and medical applications), but that is as much attributed (and probably, much, much more) to the general procedures to do projects in that field, and less the result of these kinds of safety micro-syntax.

I think in general people always want to implement more detail syntax optimization in the language, while the main issues of software engineering are much more in the libraries nowadays.

And I think these kind of borrowing syntax from all sides (that is incompatible with Delphi to start with) is pointless.
 
Title: Re: Ada style "for" loop counters
Post by: garlar27 on January 08, 2016, 01:41:07 pm
I'm sorry, in spite I understand what you wish and it's benefits. I also see what I think is a drawback:
   o- you will have a time pennalty when the for loop is nested inside another loop. Why? Because creating the variable and releasing it for each iteration.

You might think "well, compiler should add the index var to the method's init part" then compiler might get more complicated than needed just because "var section needs to gets simpler".

According to my experience:
   If var section has too many variables it can be caused by one of the following reasons:
   a- You are doing to much in a single method. You should split it.
   b- You have in hands a very rare method which is very complicated and can not be splitted. You should be very carefull with what you do and add comments to the var section as well as to the code. You will need it sooner than you might think  ;)

The same if a method has more than 50 lines and or it has 3 or more nestings (if, case, and or loops)
Title: Re: Ada style "for" loop counters
Post by: Martin_fr on January 08, 2016, 02:12:45 pm
There are a few issues.

1) auto determining the correct size of the integer type (word, int ,int64, un/signed)

IIRC (not tested) you can have overloaded procedures (word vs int). Without declaration there is a lack of clarity which one is called.

Further, if you change the return type of foo in "for a := 0 to foo", the loop will call a different foo function, that might do something completely different. (and yes there could be reasons why such overloaded functions may not be interchangeable). Similar for conflicts when mixing signed and unsigned.

2) "reserving" the identifier.
If "a" is in the var section then, I can see it is used. If it is not I might add a new boolean (or otherwise incompatible) "a", and get an error as it conflicts with the loop.

3) one identifier 2 types
Code: Pascal  [Select]
  1. begin
  2.   for a := 0 to 9 do write(a);
  3.   for a := false to true do write(a);
  4. end
  5.  
confusing, since "a" in the same procedure is at some time int, and then bool.

4)
Code: Pascal  [Select]
  1. for NameOfAGlobalVar :=
Hides a global var. Of course same can happen with any local var in the var section.
But if loop vars are no longer declared in the var block, then I must search *ALL* surrounding "for" statements, instead of just one var section.

5) There is no optional. Even if by default loop vars must be declared, and the proposal must be explicitly enabled (mode/flag).
Someone will use it, and eventually I will have to look at code that uses this.
Title: Re: Ada style "for" loop counters
Post by: BeniBela on January 08, 2016, 04:46:11 pm

1) auto determining the correct size of the integer type (word, int ,int64, un/signed)

IIRC (not tested) you can have overloaded procedures (word vs int). Without declaration there is a lack of clarity which one is called.

The loop should promote all the small ints to at least integer



Further, if you change the return type of foo in "for a := 0 to foo", the loop will call a different foo function, that might do something completely different. (and yes there could be reasons why such overloaded functions may not be interchangeable).

That is a good thing.

Especially if combined with for .. in ... Then you can make a library and hide the implementation details of the container/elements. The user does not need to know what types he is iterating over, just what methods they have. It is like using the private modifier on the types itself.

 
4)
Code: Pascal  [Select]
  1. for NameOfAGlobalVar :=
Hides a global var. Of course same can happen with any local var in the var section.
But if loop vars are no longer declared in the var block, then I must search *ALL* surrounding "for" statements, instead of just one var section.

Do not search one var section. That is just plain wrong.

You already need to check the function arguments, too. And the class fields and  properties. The fields and properties of every class and record that is used in any surrounding with block

Title: Re: Ada style "for" loop counters
Post by: Martin_fr on January 08, 2016, 05:35:48 pm

1) auto determining the correct size of the integer type (word, int ,int64, un/signed)

IIRC (not tested) you can have overloaded procedures (word vs int). Without declaration there is a lack of clarity which one is called.

The loop should promote all the small ints to at least integer
signed or unsigned? if it is int64 then this can affect comparison, depending on the other values sign.

If the function for the loop bounds changes in type, then the programs outcome may suddenly be unpredictable.

Quote

Further, if you change the return type of foo in "for a := 0 to foo", the loop will call a different foo function, that might do something completely different. (and yes there could be reasons why such overloaded functions may not be interchangeable).

That is a good thing.

Especially if combined with for .. in ... Then you can make a library and hide the implementation details of the container/elements. The user does not need to know what types he is iterating over, just what methods they have. It is like using the private modifier on the types itself.
Off topic (to my point): The type is always known at compile time (and for a library it can only depend on code inside the lib). So I do not see how your example can actually be achieved. But that is not the point I was making.

Let me make my example clearer.
Code: Pascal  [Select]
  1. procedure Bar(x: integer); overload;
  2. procedure Bar(x: int64); overload; // can not be used as replacement for the above
  3. ...
  4. for a := 0 to foo() do
  5.   bar(a);

If the "foo" changes in type, then the programs outcome may suddenly be unpredictable, because the other Bar() will not do the same thing (maybe it does act on a different set of data, and that set is not usable in the loop).

So the code will no longer work as it should. I cant see how this  is supposed to be a "good thing"

Quote
4)
Code: Pascal  [Select]
  1. for NameOfAGlobalVar :=
Hides a global var. Of course same can happen with any local var in the var section.
But if loop vars are no longer declared in the var block, then I must search *ALL* surrounding "for" statements, instead of just one var section.

Do not search one var section. That is just plain wrong.

You already need to check the function arguments, too. And the class fields and  properties. The fields and properties of every class and record that is used in any surrounding with block
Well aware of all the locations.
That does not change the validity of my point. The undeclared variable makes the search even more challenging.

Especially because it forces to repeat the work.
Right now, within a given procedure, I can establish for the entire procedure which "FOO" it refers to.
With the change, I need to repeat that search/verification, because FOO can have (any amount of) different meanings within a single procedure.
 
(Actually: using "with" blocks can cause similar issues, but the existence of one evil, is no reason to add a 2nd)
Title: Re: Ada style "for" loop counters
Post by: BeniBela on January 08, 2016, 06:43:15 pm
signed or unsigned? if it is int64 then this can affect comparison, depending on the other values sign.

If the function for the loop bounds changes in type, then the programs outcome may suddenly be unpredictable.

It always must be signed

Or it will blow up, when you write for i := 0 to list.length - 1 do ...
 
You cannot use int64 in a for-loop, or did that change? So it would always be int for numbers, so there is not much to change.

Off topic (to my point): The type is always known at compile time (and for a library it can only depend on code inside the lib). So I do not see how your example can actually be achieved.

I just discussed  that in another thread. Like this:

Code: [Select]
unit secret;

type TFoo = class
 ...
end;

unit public;
uses secret;
type TFoo = secret.TFoo;

Then you can uses public and get TFoo, but the implementation is in secret.

If you do it now, Lazarus's code tools will import secret and declare a type var v: secret.TFoo; which is not helpful. Worse than putting it in an include file.


Let me make my example clearer.
Code: Pascal  [Select]
  1. procedure Bar(x: integer); overload;
  2. procedure Bar(x: int64); overload; // can not be used as replacement for the above
  3. ...
  4. for a := 0 to foo() do
  5.   bar(a);

Such a  bar should not be in the program anyways.


Especially because it forces to repeat the work.
Right now, within a given procedure, I can establish for the entire procedure which "FOO" it refers to.
With the change, I need to repeat that search/verification, because FOO can have (any amount of) different meanings within a single procedure.
 
(Actually: using "with" blocks can cause similar issues, but the existence of one evil, is no reason to add a 2nd)

But it is just a single varible / for. A single with can bring an unlimited number of them

And usually i, j, .., then you know that they mean the nearest for loop

Title: Re: Ada style "for" loop counters
Post by: Martin_fr on January 08, 2016, 07:12:31 pm
signed or unsigned? if it is int64 then this can affect comparison, depending on the other values sign.

If the function for the loop bounds changes in type, then the programs outcome may suddenly be unpredictable.

It always must be signed

Or it will blow up, when you write for i := 0 to list.length - 1 do ...
 
You cannot use int64 in a for-loop, or did that change? So it would always be int for numbers, so there is not much to change.
Of course you can use unsigned. length/count - 1 is not the only upper bound.

If both bound are positive then unsigned loop vars will work just fine.

Quote
Code: [Select]
unit secret;

type TFoo = class
 ...

Then you can uses public and get TFoo, but the implementation is in secret.

If you do it now, Lazarus's code tools will import secret and declare a type var v: secret.TFoo; which is not helpful. Worse than putting it in an include file.
off topic, but if you want a different behaviour from codetools then suggest a change/option for that. dont change the pascal language

Quote
Code: Pascal  [Select]
  1. procedure Bar(x: integer); overload;
  2. procedure Bar(x: int64); overload; // can not be used as replacement for the above
  3. ...
  4. for a := 0 to foo() do
  5.   bar(a);

Such a  bar should not be in the program anyways.
Why? it could be a AdjustMax(arg) that keeps different value for each type of param. Then GetMax(out argOfSameType) to get the value.
Sure this could be coded better. But it is valid code, and someone might have a good reason.

As far as opinions go, IMHO it is still better than omitting the declaration of loop var.

Or it could be overloaded operators for an enum (a for loop can loop an enum). change the type of the enum, and it will no longer work.

Or a type helper, that depends on the type.

The end is: without declaring the loop var, its type can change. This change may compile, but break at run time.
If the type is fixed in the declaration, then it cant change. You may get an error at compile time, but that is (in almost all cases) so much easier to find and fix than a runtime error.

Quote
Right now, within a given procedure, I can establish for the entire procedure which "FOO" it refers to.
With the change, I need to repeat that search/verification, because FOO can have (any amount of) different meanings within a single procedure.
 
(Actually: using "with" blocks can cause similar issues, but the existence of one evil, is no reason to add a 2nd)

But it is just a single variable / for. A single with can bring an unlimited number of them

And usually i, j, .., then you know that they mean the nearest for loop
There can be 100 nested and/or in-sequence loops (well 100 may be an urgent case for refactor, but anyway).

Also as I said: "the existence of one evil, is no reason to add a 2nd"
Title: Re: Ada style "for" loop counters
Post by: DelphiFreak on January 08, 2016, 08:28:46 pm
Sooner or later someone will ask here, if we could make Pascal become "cAseSenSensiTIVE".   :D
Title: Re: Ada style "for" loop counters
Post by: GetMem on January 08, 2016, 08:31:21 pm
Quote
@DelphiFreak
Sooner or later someone will ask here, if we could make Pascal become "cAseSenSensiTIVE".   :D
Believe it or not, somebody already asked to replace begin end with {}.
Title: Re: Ada style "for" loop counters
Post by: AlanTheBeast on January 08, 2016, 09:45:41 pm
I think it shall be SynEditor-Autocomplete's job. Or be CodeTool's job.


So, (no matter AutoComplete or CodeTool) must be easy to able to write "var i : longint" into correct place within the procedure, somehow .

Which is not the proposition. 

The proposition is to eliminate the formal declaration of for loop control variables altogether and make them intelligently implicit (derived type from context - in that sense no different than what you propose - except no modification would be made to the source code.  Further, in the first instance of "i" in my example the type would be word; in the second instance the type would be longint).

Title: Re: Ada style "for" loop counters
Post by: AlanTheBeast on January 08, 2016, 09:54:23 pm
I like the idea.

Some variables do not deserve to be in the VAR list! They just increase the line of code and make the code less readable.

Precisely.

What I am not sure is why one should stop with just the loop variables: Why should not Pascal allow all the variables to be like this?  Essentially it is like the "auto" type in C++.

I would never agree to auto typing, generally.  Formalism has its place and that's why Ada has taken so much from Pascal.

OTOH, the Ada designers also realized that simple for loop controls were very often trivial and didn't need the formalism of a declaration.  So they leave it to the programmer to decide "hey, this thing counts from 1 to 10, big deal" and you don't declare it; OR "hey, this variable is very important to the understanding of the code, so let's declare it and make it clear what it does".


As I said, I like the idea but I think it needs a deep understanding of its consequences.

I believe them to be shallow in impact and clearly do not affect code from the past.  The impact on debuggers can be mitigated by symbol generation that lists each repeated temp variable with an appendage ( I_1, I_2, ...).  The only conseuence, really, is once you code with it you're restrained to compliant compilers (duh) and some might find that limiting enough.

Thanks for your positive support!
Title: Re: Ada style "for" loop counters
Post by: AlanTheBeast on January 08, 2016, 10:11:40 pm
Anyway, my suggestion is based on what AlanTheBeast described by himself in first post:
Quote
Note that such a change has no impact on any existing code but would make future coding less work
So, if you want to code faster less work, let the SynEdit do that (by using autocomplete / codetool?)

No.  That means the VAR declaration is still cluttered with trivial things that are not very useful to understanding or maintaining the code.  That is another benefit of the proposal: cleaner code that is less maintenance over the life cycle of the code.  (I'm still using stuff from the late 80's).

Example: "initialization"/"finalization" added to units.  Obviating declaring a save pointer to save the default pointer to finish the unit and restoring during the execution of that procedure; obviated setting a pointer to that finalization code -  those are still there under the hood, but the code is clearer and much more readable without them).

Quote from: AlanTheBest
Finally, Pascal now allows the abomination of C operations like       a+ = c      albeit permitted by compiler directive (relief - may it never see my machine).

Now that is awful.  Stupid.  Insane bad style.  Just as bad as curly braces.  Of course that's not at all what I've suggested.
I didn't know when fpc allow a+=c,
but if fpc did, the variables still must be declared in exact type, aren't they?

Yep: http://www.freepascal.org/docs-html/prog/progsu10.html

Of course they need to be declared as they are operated on.  I'm referring to the most simple of "counter" types.

I was attempting to make the point that some in the fpc community are allowing abominable things from the cess pit of c - and mine is not abominable - indeed it's blessed by the designers of Ada!

@AlanTheBest: if you really dislike to declare variable (is it the stupid awful?), use python!
No, do't be offended. Just maybe the best you can get: never typed-variable at all. it help you less work.

You can use insults all you like, but the fact is there are primitive things that don't need the formalism of a cluttered VAR list.  The Ada designers (who had a much more critical/safety mission in mind) recognized this despite all that they took from Pascal. 

You are not disallowed from declaring - you are given the permission to decide: oh, hell, another "i" variable is needed.  ...  OTOH, the variable might be CRITICAL_TABLE_EVENT_INDEX.  Hmm, maybe that one should go in the VAR list with a bit of explanation.

This suggestion is as much about readability and reducing errors as it is about less work and life cycle management of the source code.
Title: Re: Ada style "for" loop counters
Post by: AlanTheBeast on January 08, 2016, 10:25:32 pm

Well, the netto result vs turning the current warning into an error is shorthand, so I think it does. 

But actually a quote the FAQ more because of the second part, making a complete proposal (e.g. you don't say anything about defining the loopvar type) making a decent plan and find implementation resources etc.

Suggestions are pretty pointless without.


Suggestions start somewhere.  I think I've been very clear about what the intent and limitations are as well as some of the challenges.  With support, then I'd be happy to write a more detailed proposal and flesh out the idea much further.  But some signal that it would be seriously considered would be welcome.  The more conservative will say "don't need it" the more flexible will say "doesn't hurt me" (or "go ahead - I'll turn it off").


Quote
Of course it would only apply to the fpc compiler versions that incorporate it and therefore to IDE's that use those fpc's.  Some editors/IDE's may flag it.  It could be directive flagged on/off in case there are SQA objections (just as the unholy abomination of C operators (    a+ = c    )).
For the record, I didn't like them when they were implemented, and still don't. But they originate before 2000, multi arch and current extension policies.

Quote
Then it goes onto:
The change must fit in with the scope of the project: implementing a Pascal compiler with support for RAD and a generic DB system. This excludes features like inline SQL, and large garbage collected object frameworks.

(and IMHO implicit inline declarations are not Pascal)

No, but then a lot of things have changed in Pascal over the years.

Quote
As to the rest, the desirability for such is obvious (at least to me) - it simplifies and accelerates coding and is a well proven language feature of the most safety/mission-critical oriented language that there ever has been (Ada). 

I don't put Ada on a pedestal. It went too far IMHO. Maybe it achieved its purposes for certain highly specialized industry (like defense and medical applications), but that is as much attributed (and probably, much, much more) to the general procedures to do projects in that field, and less the result of these kinds of safety micro-syntax.

I think in general people always want to implement more detail syntax optimization in the language, while the main issues of software engineering are much more in the libraries nowadays.

And I think these kind of borrowing syntax from all sides (that is incompatible with Delphi to start with) is pointless.

Actually this is borrowing the absence of syntax  ;).

It is also is why I stated Pascal's influence on Ada from the start.  Yes, Ada can be huge, hairy and immovable, but it did improve disciplined programming in a lot of ways.  IMO, borrowing the simple loop control from Ada for Pascal would be in the best traditions of making Pascal a stronger language that is easier to write, read, debug and maintain.
Title: Re: Ada style "for" loop counters
Post by: AlanTheBeast on January 08, 2016, 11:01:53 pm

1) auto determining the correct size of the integer type (word, int ,int64, un/signed)

IIRC (not tested) you can have overloaded procedures (word vs int). Without declaration there is a lack of clarity which one is called.

Further, if you change the return type of foo in "for a := 0 to foo", the loop will call a different foo function, that might do something completely different. (and yes there could be reasons why such overloaded functions may not be interchangeable). Similar for conflicts when mixing signed and unsigned.

I believe that would be a case where a would have to be declared a priori -if- foo was indeed overloaded to the point that the correct type for a could not be determined at compile time.

2) "reserving" the identifier.
If "a" is in the var section then, I can see it is used. If it is not I might add a new boolean (or otherwise incompatible) "a", and get an error as it conflicts with the loop.

Short answer: no big deal - the error will be at compile time.

3) one identifier 2 types
Code: Pascal  [Select]
  1. begin
  2.   for a := 0 to 9 do write(a);
  3.   for a := false to true do write(a);
  4. end
  5.  
confusing, since "a" in the same procedure is at some time int, and then bool.

Confusion is in the eye of the beholder.  To be sure an Ada programmer is used to this notion and would not worry about it.  At the point where the context of "a" expires he knows it simply no longer exists.

I'd add that for style a programmer would be less likely to use this feature for false true loops (I think).  They're a bad idea in any case since one assumes false is 0 and true is 1 - so for to works - but what if it's the reverse and downto is needed....)

4)
Code: Pascal  [Select]
  1. for NameOfAGlobalVar :=
Hides a global var. Of course same can happen with any local var in the var section.
But if loop vars are no longer declared in the var block, then I must search *ALL* surrounding "for" statements, instead of just one var section.

That's very true. OTOH, the usual variable names for such are quite short (i, j, k, m, n, p, q) and usually used over a short number of lines of code.

Further, the use of simple loop control variables in a procedure should (generally) not use globally declared variable names; in turn global variable names should (generally) not be simple and undescriptive as simple loop variables typically (i,j, ..) are.  Yes, that 's style to an extent.


5) There is no optional. Even if by default loop vars must be declared, and the proposal must be explicitly enabled (mode/flag).
Someone will use it, and eventually I will have to look at code that uses this.

Bwahahahahaahahahahahahah!!!!!  :D
Title: Re: Ada style "for" loop counters
Post by: AlanTheBeast on January 08, 2016, 11:04:52 pm
Sooner or later someone will ask here, if we could make Pascal become "cAseSenSensiTIVE".   :D
Please ask it and I'll simply say that would invalidate billions of lines of code.  Thanks, cheers and goodbye.
Title: Re: Ada style "for" loop counters
Post by: Martin_fr on January 09, 2016, 12:33:30 am
2) "reserving" the identifier.
Short answer: no big deal - the error will be at compile time.
But still better if I never got the error in first.

Quote
Code: Pascal  [Select]
  1.   for a := 0 to 9 do write(a);
  2.   for a := false to true do write(a);
confusing, since "a" in the same procedure is at some time int, and then bool.

Confusion is in the eye of the beholder.  To be sure an Ada programmer is used to this notion and would not worry about it.
"an Ada programmer is used", but what about pascal programmers?
fpc is pascal, not  Ada.

Quote
4)
Code: Pascal  [Select]
  1. for NameOfAGlobalVar :=
Hides a global var.

That's very true. OTOH, the usual variable names for such are quite short (i, j, k, m, n, p, q) and usually used over a short number of lines of code.

Further, the use of simple loop control variables in a procedure should (generally) not use globally declared variable names; in turn global variable names should (generally) not be simple and undescriptive as simple loop variables typically (i,j, ..) are.  Yes, that 's style to an extent.
"should"  But there is no warranty. So the problem will exist.

To be fair: Every feature brings good and bad. The only question is, if the good outweighs the bad. Saving one line in the declaration to me does not any good, so it does not outweigh the problems.

If you are worried about reading the one line in declaration, use code folding.

You could provide a patch to hide (entirely fold, no visible line left) "{$region}". And have it fold/hide on load. Then put anything you dislike seeing into such region.

Quote
5) There is no optional.

Bwahahahahaahahahahahahah!!!!!  :D
Really? Laughter? Does that means you agree, and you are a good loser, taking it with laughter? ;)

This time I added a smiley myself, this time you may laugh.
Title: Re: Ada style "for" loop counters
Post by: AlanTheBeast on January 09, 2016, 03:22:21 pm
"an Ada programmer is used", but what about pascal programmers?
fpc is pascal, not  Ada.

I've made the point that Ada contains a lot of Pascal in its DNA.  But the Ada designers saw declaring indexes as a waste of time in most cases.  They did not make it "illegal" for those cases where readability desires it. 

It is something one adopts and loves pretty quick and will actually not harm Pascal programmers at all.

Quote
4)
Code: Pascal  [Select]
  1. for NameOfAGlobalVar :=
Hides a global var.

That's very true. OTOH, the usual variable names for such are quite short (i, j, k, m, n, p, q) and usually used over a short number of lines of code.

Further, the use of simple loop control variables in a procedure should (generally) not use globally declared variable names; in turn global variable names should (generally) not be simple and undescriptive as simple loop variables typically (i,j, ..) are.  Yes, that 's style to an extent.

"should"  But there is no warranty. So the problem will exist.
[/quote]

And on that day the programmer will have a compile time bug and regret (with good reason) all those simple single letter global variables that he knew he should not have declared (Ahem, I have a lot of units that are thus littered so it's not like I would be able to use this at large in some of those units.  OTOH, this change would not affect the ability to compile those units at all - only if I made such changes.  Thankfully I tend to writing units that are small.

To be fair: Every feature brings good and bad. The only question is, if the good outweighs the bad. Saving one line in the declaration to me does not any good, so it does not outweigh the problems.

If you are worried about reading the one line in declaration, use code folding.

You could provide a patch to hide (entirely fold, no visible line left) "{$region}". And have it fold/hide on load. Then put anything you dislike seeing into such region.

It's not about hiding existing declarations.   The notion of these undeclared but properly typed indexes is simplicity in programming, reading and in maintaining code over the long haul.

5) There is no optional.

Bwahahahahaahahahahahahah!!!!!  :D
[/quote]
Really? Laughter? Does that means you agree, and you are a good loser, taking it with laughter? ;)

This time I added a smiley myself, this time you may laugh.
[/quote]

Call it a well deserved grin.

Loser? Not at all.  I believe strongly that this is a "good thing" to add to Pascal just as the Ada designers saw that it was a good thing to do despite their otherwise heavy formalism.

Mr. Wirth started a language based on strong declarations for good reason - not the least the lack of sophistication in compilers - it was probably easier to be very strict than it would have been to have some automatic features.
Title: Re: Ada style "for" loop counters
Post by: Martin_fr on January 09, 2016, 03:55:07 pm
well agree to disagree.

You (appear) to believe, that optional exists for such a feature.

I disagree. Based on my experience, optional does not exist (yes I am serious, no laughter this time please).


If (for argument sake) optional does not exist, then the above will cause harm (to some people).

This is not about how you would use it, you would not be the only one using it.

-------------
Besides what are the benefits?

- less typing (IIRC that was dismissed / should be taken care of, by codetool)
- less code to read (apparently not, since hiding/folding is dismissed as solution

That leaves automatically follow the type of the bounds if they change.

Using a smaller (word instead of int) type for optimization? I am not sure that really will optimize a lot (maybe on embedded), well and 2 bytes on the stack, if it is not in a register.
Besides, a variable that is declared as int, can be optimized the same way, if the compiler can detect that it never holds values that do not fit into word (and is not accessed via pointer or similar)
In any case the rules for the optimization are the same in both cases.

So what are the benefits then?
Maybe that the loop originally written for integer, can still compile if the bounds change to some enum? How likely is that? Both bounds would need to change in the same way. And if they do, any operation  (compare, add, use as index,...) on the loop var, done in the loop must be supported on the new type. IMHO rather unlikely.

What did I miss, what is the benefit?


--------------
the "looser" comment was clearly marked as a joke. I never indented to make any statement with this.
Title: Re: Ada style "for" loop counters
Post by: marcov on January 09, 2016, 03:58:06 pm
Optimization is a non argument. If the loopcounter is immutable, then the compiler can register it and determine its own bounderies. That has nothing to do with syntax.
Title: Re: Ada style "for" loop counters
Post by: AlanTheBeast on January 15, 2016, 12:19:04 am
well agree to disagree.

You (appear) to believe, that optional exists for such a feature.

I disagree. Based on my experience, optional does not exist (yes I am serious, no laughter this time please).

At this point I don't even know what you're on about.   You seem to be throwing objections for that sake alone.

If (for argument sake) optional does not exist, then the above will cause harm (to some people).

This is not about how you would use it, you would not be the only one using it.

To be sure.  But then, since it is a simple and clear enough thing, I don't think that a serious look at how it would be implemented would really find all that much issue.  I mean really, if a compiler can determine a simple type for the index that is no different than how a programmer would declare it, then there isn't much issue.  That is how it's done in Ada.  And where the compiler can't digest it, then a warning/fail is issued.

Besides what are the benefits?

- less typing (IIRC that was dismissed / should be taken care of, by codetool)

a- you might dismiss it, I don't
b- codetool inserting the VAR is not implementing the feature.

- less code to read (apparently not, since hiding/folding is dismissed as solution

Not so much that it is "less code to read" as it is "less clutter in the VAR list".

That leaves automatically follow the type of the bounds if they change.

Using a smaller (word instead of int) type for optimization? I am not sure that really will optimize a lot (maybe on embedded), well and 2 bytes on the stack, if it is not in a register.
Besides, a variable that is declared as int, can be optimized the same way, if the compiler can detect that it never holds values that do not fit into word (and is not accessed via pointer or similar)
In any case the rules for the optimization are the same in both cases.

So, no real issue given sober constraints.  If the range is variable, then the variable define the range.  In the unlikely case that the the bounds are pointer accessed, they are stil type constrained.  If the bounds are overloaded, then simply throw a failure and explain why.

So what are the benefits then?
Maybe that the loop originally written for integer, can still compile if the bounds change to some enum? How likely is that? Both bounds would need to change in the same way. And if they do, any operation  (compare, add, use as index,...) on the loop var, done in the loop must be supported on the new type. IMHO rather unlikely.

What did I miss, what is the benefit?


You didn't miss making the simple into complex, that is for sure.

--------------
the "looser" comment was clearly marked as a joke. I never indented to make any statement with this.

I didn't take it any other way.
Title: Re: Ada style "for" loop counters
Post by: Martin_fr on January 15, 2016, 01:52:59 pm
At this point I don't even know what you're on about.   You seem to be throwing objections for that sake alone.
Not at all, or not intentional.
I am not sure, if the comments left by some of the members of the fpc team, indicate that the idea is already rejected. If so, then the argument is indeed moot. Otherwise, I do have a point.

Non sure which part you are not sure about. So below may contain some repeats. Sorry.

First about "optional". And that really is the all defining point. (Despite your initial laughter on this)

*IF* this could be truly optional, then it would never affect me (or anyone who has my view on it). If it would never affect me, then I had no other arguments. (Same as, I am not using language X, so I do not care what people do to it)

But it will (as in: there is a possibility) affect me. My boss may ask me to use a 3rd party lib, that uses it, and I may have to read the code.

So my reason is: I argue about it, because it can affect me.



This is not about how you would use it, you would not be the only one using it.
at how it would be implemented would really find all that much issue.
This is not about implementation. I am not maintaining the compiler, so that does not matter do me. And I wouldn't ever notice, if fpc would change a few millisec in speed (faster/slower), or fpc.exe grew a bit in size. None of that is my problem.

You said, you would use it "reasonable", e.g. only short var names to minimize (IMHO still not avoid) conflict with identifiers in other scopes. But other people will (not "may", definetely "will") use it more aggressive. (And I (or others like me) may/will in future be forced to read there code).



- less typing (IIRC that was dismissed / should be taken care of, by codetool)
a- you might dismiss it, I don't
Ok.This is personal preference. So it cant be argued.
But IIRC on the link to the fpc wiki, it is mentioned that this is not accepted as reason for a feature. (I didnt write that wiki)


- less code to read (apparently not, since hiding/folding is dismissed as solution

Not so much that it is "less code to read" as it is "less clutter in the VAR list"
And as I said, to me personally, this decreases readability of the overall code. (And I am probably not alone on this) So this argument goes both ways.

Beside, if codetools would (for loop vars) insert:
Code: Pascal  [Select]
  1. {$region 'loop vars' /hide}
  2. var
  3.   i: integer;
  4. {$endregion}
  5.  
The editor can be patched to entirely hide (like comment) this. So the "clutter" would never be visible. (Yet I could disable region hiding in my options, so it would not affect me).



That leaves automatically follow the type of the bounds if they change.

Using a smaller (word instead of int) type for optimization? ...
In any case the rules for the optimization are the same in both cases.
So, no real issue given sober constraints.  If the range is variable, then the variable define the range.  ...
I dont understand. You still havent explained what the benefit is (well: less typing, is now on).

- optimization is not, because it can be done, even if the type is declared.
- following the type of the bounds. That could be seen as benefit, but it is extremely rare (as both bounds need to change), and it can also be a danger, as unintended changes to the bound will silently keep compiling. So this evens out (In my book the danger even weighs more than the "benefit")

There is one other point: Having a smaller scope var the loop var. Such scopes where proposed before and rejected. And to me they decrease readability, because they also introduce extra work to find all variables/properties/members/identifiers that are visible to a procedure. (See my comment on "with is bad, because it does something similar).



You didn't miss making the simple into complex, that is for sure.
Sorry, I did not MAKE it complex. I merely pointed out how complex this is (and always was).



Conclusion. In my attempt to learn the benefits:

- I accept that less typing matters to you (But it is not (enough of a) reason to me).

- You find the presence of the loop var in the var section "clutter" (less readable?). To me there absence decreases readability. (I explained that in detail, in previous post)

Both of those are personal preferences. Except the latter (absence) is a fundamental change to the definition of pascal, and would void one of the reasons why I like pascal. So it would be a severe loss.

For all other things, that I could imagine someone might see as benefit, I have explained why they are not.

- optimization of generated machine code: possible in exactly the same way, even if var is declared

- changing type, if boundary changes: can go wrong as easily as it might be helpful / in any case: it is rare to ever happen at all

- micro-scoped var declaration: see argument on "absence in var block"
Title: Re: Ada style "for" loop counters
Post by: BeniBela on January 15, 2016, 02:29:52 pm


I dont understand. You still havent explained what the benefit is (well: less typing, is now on).

There are a lot of small benefits (like those you listed). They add up
Quote from: Martin_fr


[quote author=Martin_fr link=topic=31016.msg198602#msg198602 date=1452862379

Code: Pascal  [Select]
  1. {$region 'loop vars' /hide}
  2. var
  3.   i: integer;
  4. {$endregion}
  5.  

You still see that, when you commit the files.

And now you have 4 lines for what used to be one. This is way worse.




Also CodeTools do not remove the declaration, when you remove the loop. Then you have to search through the entire file to remove old loop vars to fix pointless hints
Title: Re: Ada style "for" loop counters
Post by: Martin_fr on January 15, 2016, 03:04:52 pm
There are a lot of small benefits (like those you listed). They add up
Thats "less typing" / "less reading" (clutter) only. (and from below: less clean up).

And the 2nd (less reading) is (to others) a severe disadvantage/damage.

We obviously weigh those different. But imho, you need much much stronger (and more) reasons, if you want to change one of the fundamentals of pascal (i.e. the need to declare ALL vars in advance).

Quote
You still see that, when you commit the files.
And now you have 4 lines for what used to be one. This is way worse.
you can put it all on one line. then that line is also easy to ignore during commits.

But yes, they are still in there. That is the point. Removing them severely damages readability of the code. (well not to you, not to ADA programmers, but to some others / and those others are people who had chosen Pascal, and not ADA)

Quote
Also CodeTools do not remove the declaration, when you remove the loop. Then you have to search through the entire file to remove old loop vars to fix pointless hints
1) A clean up of this kind could be added (delete selection and clean variables)
2) That applies to any other code removal too.

Solving this via (1) would be much more universal, as it would help in all cases, rather than a tiny subset only.

Title: Re: Ada style "for" loop counters
Post by: garlar27 on January 15, 2016, 05:33:10 pm
IMHO it is too much work on the compiler side (and it could be much more than we can imagine since it breaks pascal's definition) for some benefits for which not everybody agree.
Title: Re: Ada style "for" loop counters
Post by: bylaardt on January 15, 2016, 08:39:40 pm
@ AlanTheBest

Code: Pascal  [Select]
  1. procedure Test;
  2.   procedure ShowA;
  3.   begin
  4.     writeln(a);
  5.   end;
  6. begin
  7.   for a:=0 to 10 do
  8.     ShowA;
  9. end;
  10.  
Is this a valid code?
because my scope concept says "Are you kiding me?"
Title: Re: Ada style "for" loop counters
Post by: BeniBela on January 15, 2016, 09:19:35 pm

Code: Pascal  [Select]
  1. procedure Test;
  2.   procedure ShowA;
  3.   begin
  4.     writeln(a);
  5.   end;
  6. begin
  7.   for a:=0 to 10 do
  8.     ShowA;
  9. end;
Is this a valid code?

Of course not !

The a should only be visible inside the for statement. The procedure is not inside the for statement.

However, this should be valid code:


Code: Pascal  [Select]
  1. procedure Test;
  2. begin
  3.   for a:=0 to 10 do begin
  4.     procedure ShowA;
  5.     begin
  6.       writeln(a);
  7.     end;
  8.     ShowA;
  9.   end;
  10. end;
  11.  

And I am not kidding
Title: Re: Ada style "for" loop counters
Post by: BeniBela on January 15, 2016, 09:27:10 pm
And of course this should not be valid either:


Code: Pascal  [Select]
  1. procedure Test;
  2. begin
  3.   for a:=0 to 10 do begin
  4.     procedure ShowA;
  5.     begin
  6.       writeln(a);
  7.     end;
  8.   end;
  9.   ShowA;
  10. end;
  11.  


but this one again would:

Code: Pascal  [Select]
  1. procedure Test;
  2. var p: TProcedure;
  3. begin
  4.   for a:=0 to 10 do begin
  5.     p := ( procedure ShowA;
  6.     begin
  7.       writeln(a);
  8.     end)
  9.   end;
  10.   p();
  11. end;
  12.  


and print 10 and nothing else

while this should print 0 to 10 :

Code: Pascal  [Select]
  1. procedure Test;
  2. var p: array[0..10] of TProcedure;
  3. begin
  4.   for a:=0 to 10 do begin
  5.     p[a] := ( procedure ShowA;
  6.     begin
  7.       writeln(a);
  8.     end)
  9.   end;
  10.   for q in p do q();
  11. end;
  12.  


Is this not awesome?
Title: Re: Ada style "for" loop counters
Post by: garlar27 on January 15, 2016, 09:45:49 pm
And of course this should not be valid either:


Code: Pascal  [Select]
  1. procedure Test;
  2. begin
  3.   for a:=0 to 10 do begin
  4.     procedure ShowA;
  5.     begin
  6.       writeln(a);
  7.     end;
  8.   end;
  9.   ShowA;
  10. end;
  11.  


but this one again would:

Code: Pascal  [Select]
  1. procedure Test;
  2. var p: TProcedure;
  3. begin
  4.   for a:=0 to 10 do begin
  5.     p := ( procedure ShowA;
  6.     begin
  7.       writeln(a);
  8.     end)
  9.   end;
  10.   p();
  11. end;
  12.  


and print 10 and nothing else

while this should print 0 to 10 :

Code: Pascal  [Select]
  1. procedure Test;
  2. var p: array[0..10] of TProcedure;
  3. begin
  4.   for a:=0 to 10 do begin
  5.     p[a] := ( procedure ShowA;
  6.     begin
  7.       writeln(a);
  8.     end)
  9.   end;
  10.   for q in p do q();
  11. end;
  12.  


Is this not awesome?
NO, I DON'T THINK SO.

I never could see the "good part" of those "disposable"  %) function/procedure. Is bloody awfull to mantain  :o :o
Title: Re: Ada style "for" loop counters
Post by: bylaardt on January 16, 2016, 12:23:51 am
procedure "ShowA" is in the same scope as the "a" was declared and i can't access "a"?

This is a distortion of scope concept, sorry if just me who think so, but IMHO this is unacceptable.
if anyone implement this, rename the language to another name, because this is not Pascal, and not Ada too, maybe another dialect, like "lazy's pascal"  :-[
Title: Re: Ada style "for" loop counters
Post by: BeniBela on January 16, 2016, 01:40:43 am
procedure "ShowA" is in the same scope as the "a" was declared and i can't access "a"?


Obviously showA is not in the same scope as a. the first a occurs after the end of showA

Or did you mean my second posted code? There showA can access a just fine. But showA cannot be called from outside the loop
Title: Re: Ada style "for" loop counters
Post by: bylaardt on January 16, 2016, 02:46:50 pm
The proposal of this post is suppress the var declaration from for control variables, to simplify or make the code more "readable"

Then this:
Code: Pascal  [Select]
  1. procedure Test;
  2. var
  3.  a:byte;  //<-- this was suppress
  4.   procedure ShowA;
  5.   begin
  6.     writeln(a);
  7.   end;
  8. begin
  9.   for a:=0 to 10 do
  10.     ShowA;
  11. end;

becomes:

Code: Pascal  [Select]
  1. procedure Test;
  2. var p: array[0..10] of TProcedure;
  3. begin
  4.   for a:=0 to 10 do begin
  5.     p[a] := ( procedure ShowA;
  6.     begin
  7.       writeln(a);
  8.     end)
  9.   end;
  10.   for q in p do q();
  11. end;

Thanks benibella. you have a good point, but i really can't see a real advantage to this proposal, except make lazys programmers happy.
i remember my teacher saying how angry any new pascal student when compiler show messages like:
";" found, expected ")"
... and saying "why not just compile it and closing by himself?"

I believe compiler suppress is a bad idea in any cases;
Title: Re: Ada style "for" loop counters
Post by: FTurtle on January 17, 2016, 05:02:22 pm
By the way:

Code: Pascal  [Select]
  1. procedure Test;
  2. var
  3.  a:byte;  //<-- this was suppress
  4.  

See here:
http://wiki.freepascal.org/Example:_Why_the_loop_variable_should_be_of_signed_type
Title: Re: Ada style "for" loop counters
Post by: AlanTheBeast on January 17, 2016, 05:04:35 pm
The proposal of this post is suppress the var declaration from for control variables, to simplify or make the code more "readable"

Thanks benibella. you have a good point, but i really can't see a real advantage to this proposal, except make lazys programmers happy.
i remember my teacher saying how angry any new pascal student when compiler show messages like:
";" found, expected ")"
... and saying "why not just compile it and closing by himself?"

I believe compiler suppress is a bad idea in any cases;


Repeating what I've said elsewhere.

1. It is most definitely not about making lazy programmers happy.

2. It is about simplifying the var declaration which improves

3. As others have raised ridiculous examples to ridicule this proposal - your ridiculous example ";" remains as ridiculous as the others.

4. And finally, not only is this not inspired by laziness, it is inspired by a language that is both largely influenced by Pascal and also much more type rigid than Pascal.  Yet for the purpose of loop indexes they had a fit of rational simplicity.
Title: Re: Ada style "for" loop counters
Post by: molly on January 17, 2016, 05:07:13 pm
By the way:

See here:
http://wiki.freepascal.org/Example:_Why_the_loop_variable_should_be_of_signed_type
Yups, that's a very annoying one. Especially when converting code from c.

Unfortunately it is not always possible to use a signed type in which case you end up using while loops (or a lot of casting) :-(
Title: Re: Ada style "for" loop counters
Post by: AlanTheBeast on January 17, 2016, 05:15:26 pm

However, this should be valid code:


Code: Pascal  [Select]
  1. procedure Test;
  2. begin
  3.   for a:=0 to 10 do begin
  4.     procedure ShowA;
  5.     begin
  6.       writeln(a);
  7.     end;
  8.     ShowA;
  9.   end;
  10. end;
  11.  

And I am not kidding

You can't declare a procedure within the executing part of a procedure.
Title: Re: Ada style "for" loop counters
Post by: taazz on January 17, 2016, 05:23:43 pm
You can't declare a procedure within the executing part of a procedure.
https://en.wikipedia.org/wiki/Anonymous_procedure (https://en.wikipedia.org/wiki/Anonymous_procedure)
Title: Re: Ada style "for" loop counters
Post by: BeniBela on January 17, 2016, 05:52:05 pm

However, this should be valid code:


Code: Pascal  [Select]
  1. procedure Test;
  2. begin
  3.   for a:=0 to 10 do begin
  4.     procedure ShowA;
  5.     begin
  6.       writeln(a);
  7.     end;
  8.     ShowA;
  9.   end;
  10. end;
  11.  

And I am not kidding

You can't declare a procedure within the executing part of a procedure.

But I want to!



I just found a great example with a for in loop. There you  must use this automatically typed variable. You cannot loop without it:

Code: Pascal  [Select]
  1. var a: array of record
  2.   x, y: integer;
  3. end;
  4. begin
  5.   SetLength(a, 10);
  6.   for r in a do begin
  7.     writeln(r.x, ' ', r.y);
  8.   end;
  9. end
  10.  

You cannot declare r as r: record x, y: integer; end. It would be another record type. If a is from a library, it is given and  you cannot change its type.

It is impossible to use for-in without autodeclared types.
Title: Re: Ada style "for" loop counters
Post by: wp on January 17, 2016, 06:05:37 pm

However, this should be valid code:


Code: Pascal  [Select]
  1. procedure Test;
  2. begin
  3.   for a:=0 to 10 do begin
  4.     procedure ShowA;
  5.     begin
  6.       writeln(a);
  7.     end;
  8.     ShowA;
  9.   end;
  10. end;
  11.  

And I am not kidding

You can't declare a procedure within the executing part of a procedure.

But I want to!

What would be the advantage over this valid code?
Code: Pascal  [Select]
  1. procedure Test;
  2. var
  3.   a: Integer;
  4.  
  5.   procedure ShowA;
  6.   begin
  7.     writeln(a);
  8.   end;
  9.  
  10. begin
  11.   for a:=0 to 10 do begin
  12.     ShowA;
  13.   end;
  14. end;
  15.  
Title: Re: Ada style "for" loop counters
Post by: Leledumbo on January 17, 2016, 06:53:25 pm
I just found a great example with a for in loop. There you  must use this automatically typed variable. You cannot loop without it:

Code: Pascal  [Select]
  1. var a: array of record
  2.   x, y: integer;
  3. end;
  4. begin
  5.   SetLength(a, 10);
  6.   for r in a do begin
  7.     writeln(r.x, ' ', r.y);
  8.   end;
  9. end
  10.  

You cannot declare r as r: record x, y: integer; end. It would be another record type. If a is from a library, it is given and  you cannot change its type.

It is impossible to use for-in without autodeclared types.
If there's such a library, that's a badly written one. Seriously, ask the author to write Pascal correctly. Structured types must be defined and exported in interface section. Laziness has no support in Pascal.
Title: Re: Ada style "for" loop counters
Post by: Martin_fr on January 17, 2016, 06:55:58 pm
If there's such a library, that's a badly written one. Seriously, ask the author to write Pascal correctly. Structured types must be defined and exported in interface section. Laziness has no support in Pascal.
+1

Title: Re: Ada style "for" loop counters
Post by: marcov on January 17, 2016, 06:57:38 pm
I actually agree with Benibela that this is a weak point, but it can't really be helped, except by declaring a separate type.

Pascal is a strong typed language, and too much weakening of the principle will make the whole system come crashing down. And there has been quite some weakening already (like variants, though for a more lofty goal than saving on typing)
Title: Re: Ada style "for" loop counters
Post by: Thaddy on January 17, 2016, 07:03:27 pm
I actually agree with Benibela that this is a weak point, but it can't really be helped, except by declaring a separate type.

Pascal is a strong typed language, and too much weakening of the principle will make the whole system come crashing down. And there has been quite some weakening already (like variants, though for a more lofty goal than saving on typing)

Yes, but type inference still means strongly typed, or doesn't it? But if the compiler infers, programmers tend to create bugs.
Title: Re: Ada style "for" loop counters
Post by: BeniBela on January 17, 2016, 07:49:23 pm

If there's such a library, that's a badly written one. Seriously, ask the author to write Pascal correctly. Structured types must be defined and exported in interface section. Laziness has no support in Pascal.

I wrote that library!

I think it is a great way to handle internal types that have to be there, but the library user should be discouraged to create new instances of them. Exporting them would be the worst.


Pascal is a strong typed language

And ADA is supposed to be an even strongerly typed language!
Title: Re: Ada style "for" loop counters
Post by: taazz on January 17, 2016, 08:08:14 pm

If there's such a library, that's a badly written one. Seriously, ask the author to write Pascal correctly. Structured types must be defined and exported in interface section. Laziness has no support in Pascal.

I wrote that library!

I think it is a great way to handle internal types that have to be there, but the library user should be discouraged to create new instances of them. Exporting them would be the worst.

then do it correctly no half a$$ solutions
Code: Pascal  [Select]
  1. procedure Test;
  2. type
  3.   TInternal = record
  4.     x, y: integer;
  5.   end;
  6. var
  7.   a: array of Tinternal;
  8.   r: TInternal;
  9. begin
  10.   SetLength(a, 10);
  11.   for r in a do begin
  12.     writeln(r.x, ' ', r.y);
  13.   end;
  14. end;
  15.  
Title: Re: Ada style "for" loop counters
Post by: Leledumbo on January 17, 2016, 08:33:46 pm
I wrote that library!
I stand with my words that it's a badly written library, so fix it.
Title: Re: Ada style "for" loop counters
Post by: Martin_fr on January 17, 2016, 08:45:30 pm
I wrote that library!

I think it is a great way to handle internal types that have to be there, but the library user should be discouraged to create new instances of them. Exporting them would be the worst.

Now you say you wrote it that way, to prevent people from using the type, and then you say that the language should be changed so that people can use the type.

Do you or do you not want that type to be used?

as for your loop, iterate the index (0..9), instead of the elements.
Title: Re: Ada style "for" loop counters
Post by: marcov on January 17, 2016, 09:15:16 pm
And ADA is supposed to be an even strongerly typed language!

Well, if ADA commonly infers the type of loopvariables, we can lay that illusion to rest.
Title: Re: Ada style "for" loop counters
Post by: AlanTheBeast on January 18, 2016, 12:45:54 am
You can't declare a procedure within the executing part of a procedure.
https://en.wikipedia.org/wiki/Anonymous_procedure (https://en.wikipedia.org/wiki/Anonymous_procedure)

... in Pascal?  I tried compiling one a few minutes ago and it certainly did not work.
Title: Re: Ada style "for" loop counters
Post by: AlanTheBeast on January 18, 2016, 12:54:17 am

What would be the advantage over this valid code?
Code: Pascal  [Select]
  1. procedure Test;
  2. var
  3.   a: Integer;
  4.  
  5.   procedure ShowA;
  6.   begin
  7.     writeln(a);
  8.   end;
  9.  
  10. begin
  11.   for a:=0 to 10 do begin
  12.     ShowA;
  13.   end;
  14. end;
  15.  

Nothing wrong with that - if one had a simple procedure that should be private to that procedure, then by all means.  I have a few of those in code here and there but really not much.
Title: Re: Ada style "for" loop counters
Post by: AlanTheBeast on January 18, 2016, 12:56:29 am
@ AlanTheBest

Code: Pascal  [Select]
  1. procedure Test;
  2.   procedure ShowA;
  3.   begin
  4.     writeln(a);
  5.   end;
  6. begin
  7.   for a:=0 to 10 do
  8.     ShowA;
  9. end;
  10.  
Is this a valid code?
because my scope concept says "Are you kiding me?"

Looks valid to me.  Certainly will compile and certainly will run.  All it does is make "ShowA" private to Test.  Indeed you could have other ShowA's elsewhere in the code and they wouldn't get called from Test.
Title: Re: Ada style "for" loop counters
Post by: AlanTheBeast on January 18, 2016, 01:03:20 am

And ADA is supposed to be an even strongerly typed language!

Yes.  And despite that the Ada designers, so severe in so many things, saw loop control variables as something trivial enough to not need definition in the vars list when the compiler could safely determine the type for the index.

This may seem heresy to Pascal programmers (and I am one) but I also see the simple clarity of it.  I've written some small Ada projects and this becomes the absolute least of ones worries.
Title: Re: Ada style "for" loop counters
Post by: AlanTheBeast on January 18, 2016, 01:03:57 am
By the way:

See here:
http://wiki.freepascal.org/Example:_Why_the_loop_variable_should_be_of_signed_type
Yups, that's a very annoying one. Especially when converting code from c.

Unfortunately it is not always possible to use a signed type in which case you end up using while loops (or a lot of casting) :-(

I usually use unsigned (where appropriate) by habit from programming in assembler and always being very conscious of what the range of the variable should be.

The example cited is pretty awful, because another thing I strenuously avoid is using the last value of an index after a for loop.  That's always been considered dangerous for portability as you don't really know how different compilers, versions of compilers or even modes within compilers will leave the variable after the loop is finished.  What if the index is done in register and in turn is not written to the variable when the loop exits?  Even if saved on each loop, the compare is done in register for the exit condition and not (or is) saved before the exit.

The proposed use of non-declared variables in for loops makes such unsafe code impossible too as it is not in scope after the loop exit. 

An additional benefit.
Title: Re: Ada style "for" loop counters
Post by: AlanTheBeast on January 18, 2016, 01:05:26 am

Pascal is a strong typed language, and too much weakening of the principle will make the whole system come crashing down. And there has been quite some weakening already (like variants, though for a more lofty goal than saving on typing)

{Edited}
Removing a var declaration where the sole purpose of the variable is to control a loop and be used within that loop does not weaken anything at all.
Secondly, the benefits of the proposal do mean a little less typing, but that is the least of the benefits (which I've pointed out elsewhere).


Title: Re: Ada style "for" loop counters
Post by: taazz on January 18, 2016, 01:31:34 am
You can't declare a procedure within the executing part of a procedure.
https://en.wikipedia.org/wiki/Anonymous_procedure (https://en.wikipedia.org/wiki/Anonymous_procedure)

... in Pascal?  I tried compiling one a few minutes ago and it certainly did not work.
freepascal is a bit behind from other pascal compilers but as far as I know there is already some kind of implementation in SVN I just don't remember if it is a fork or it has been merged to the developers version already. So yeah it will be possible in the future.

And ADA is supposed to be an even strongerly typed language!
This may seem heresy to Pascal programmers (and I am one) but I also see the simple clarity of it.  I've written some small Ada projects and this becomes the absolute least of ones worries.
For loop variable values are undefined after the loop so loosing the declaration will not be that bad. I just don't like auto declared variables outside the for loop, I had a huge number of problems with this feature in VB 6 until I disabled it. So as long as this feature is 1) application wide not unit specific and 2) a choice I can turn off for all packages units that are used in that application I'm ok with it I guess.
Title: Re: Ada style "for" loop counters
Post by: AlanTheBeast on January 18, 2016, 01:40:01 am
You can't declare a procedure within the executing part of a procedure.
https://en.wikipedia.org/wiki/Anonymous_procedure (https://en.wikipedia.org/wiki/Anonymous_procedure)

... in Pascal?  I tried compiling one a few minutes ago and it certainly did not work.
freepascal is a bit behind from other pascal compilers but as far as I know there is already some kind of implementation in SVN I just don't remember if it is a fork or it has been merged to the developers version already. So yeah it will be possible in the future.

 :o I hope not.  That is really ugly.


And ADA is supposed to be an even strongerly typed language!
This may seem heresy to Pascal programmers (and I am one) but I also see the simple clarity of it.  I've written some small Ada projects and this becomes the absolute least of ones worries.
For loop variable values are undefined after the loop so loosing the declaration will not be that bad. I just don't like auto declared variables outside the for loop, I had a huge number of problems with this feature in VB 6 until I disabled it. So as long as this feature is 1) application wide not unit specific and 2) a choice I can turn off for all packages units that are used in that application I'm ok with it I guess.

I certainly don't disagree with that - indeed it's one of the strong points of the proposal: outside the loop, that variable ceases to exist and cannot be used at all.  This prevents using the last value of the for loop control variable which is not guaranteed in Pascal (that I recall).
Title: Re: Ada style "for" loop counters
Post by: bylaardt on January 18, 2016, 02:33:51 am
@ fturtle:

why not unsigned?
why not byte from 0 to 10?
Any ordinal types with range can be a for loop long as you respect this range.

make some tests  yourself:

Code: Pascal  [Select]
  1. procedure TPrincipal.AjudaManualClick(Sender: TObject);
  2. type
  3.   CalendarMode=(cmMonthly,cmQuarterly,cmSemiannual,cmAnnual);
  4. var
  5.   c:char;
  6.   d:CalendarMode;
  7.   v:boolean;
  8. begin
  9.   for c:= 'a' to 'z' do
  10.     writeln(c);
  11.   for v:= false to true do
  12.     writeln(v);
  13.   for d:= cmMonthly to cmannual do
  14.     writeln(d);
  15. end;
  16.  
Title: Re: Ada style "for" loop counters
Post by: FTurtle on January 18, 2016, 12:08:43 pm
The example cited is pretty awful, because another thing I strenuously avoid is using the last value of an index after a for loop.  That's always been considered dangerous for portability as you don't really know how different compilers, versions of compilers or even modes within compilers will leave the variable after the loop is finished.

Right words in wrong case.
In example, the loop variable not used outside of loop.
The values displayed after the completion of the loop are obtained without use of the loop variable:

Quote
  AList.Clear;
  for i:=0 to AList.Count-1 do
  WriteLn(i:3, ':  '{, AList[ i]});  // exception if uncomment
 
  WriteLn('-------------');
  AsShortInt := AList.Count-1;
  AsByte := AList.Count-1;
  WriteLn('ShortInt = ', AsShortInt);
  WriteLn('Byte     = ', AsByte);

But thank you for your comment anyway.
I modified example to make it more clear:

Code: Pascal  [Select]
  1.   AList.Clear;
  2.   Last_AsByte := AList.Count-1;
  3.  
  4.   WriteLn('  Empty list:');
  5.   WriteLn('  for i:=0 to ', Last_AsByte);
  6.   WriteLn('  ---------------');
  7.  
  8.   for i:=0 to AList.Count-1 do
  9.     WriteLn(i:3, ':  '{, AList[i]});  // exception if uncomment
  10.  
  11.   WriteLn('-----------------');
  12.  
Title: Re: Ada style "for" loop counters
Post by: FTurtle on January 18, 2016, 12:50:26 pm
why not unsigned?
why not byte from 0 to 10?
Any ordinal types with range can be a for loop long as you respect this range.

Read "loop variable should be of signed type" like
"loop variable usually should be of signed type"
instead "loop variable always must be of signed type"
and then everything will be OK.
There are always exceptions to rule.
But if you write something like for i:=0 to SomeCount-1, the loop variable must be a signed type (of course, if your goal is not searching for adventures).
Title: Re: Ada style "for" loop counters
Post by: Martin_fr on January 18, 2016, 01:44:25 pm
"loop variable usually should be of signed type"
instead "loop variable always must be of signed type"

And that is one of the big issues with this. The compiler can only do best guess, and it sometimes will go wrong.

"Not a problem", I was told. In those cases I can still declare the loop var:
Code: Pascal  [Select]
  1. var i: qword;
  2. ...
  3. for i := OldCount to Count - 1 do // at this point, it is guaranteed that count will be  >=1
  4. ...
qword is needed because count could be a very large value ( >high(int64) ). And yes, this can happen, e.g. with sparse lists, or if values are calculated rather than stored.

But anyway, it works, so why am I mentioning it?

Well, because as I regularly do, some month later, I refactor, and I need to rename "i" to  "idx".

Because (if the feature was available) loop vars are normally not declared, I expect that to be the case here too. I only rename in code, I do not update the declaration (why should I?) .
It compiles fine. It passes my basic tests, despite now it is an Int64 (auto detected by compiler, "idx" is not declared).

I ship my app. A few weeks later I get lots of calls from my clients.
The app keeps crashing.

All so someone could be a bit lazier. type a bit less, read a bit less.

Title: Re: Ada style "for" loop counters
Post by: Martin_fr on January 18, 2016, 01:52:26 pm
    Readability of the vars section: focus on things that are important/relevant
And this has bothered me all the time. How does one determine the importance of a variable?

My code doesn't have unimportant or less important variables.
Loop variables are variables too, they are important too, just as much as any other. (If they were not, that would imply, that the entire loop was not important, and leave the question why I did write the loop at all)

If anything (not just loops) is not or less relevant to the current procedure, then it should be placed into its own procedure (where it then will be relevant). And I should call the procedure, rather than inlining the code.

So really the only reason not to have a variable in the var block, is because the code using it should not be in the code block (of this procedure) either. But hey, that is already supported.
Title: Re: Ada style "for" loop counters
Post by: BeniBela on January 18, 2016, 03:09:31 pm

Now you say you wrote it that way, to prevent people from using the type, and then you say that the language should be changed so that people can use the type.

Do you or do you not want that type to be used?


I want it to be used like this (http://forum.lazarus.freepascal.org/index.php?topic=30900.0).


Not being used without going through hops, but if it could not be used at all, the library could not implement it.

This is what effective programming looks like without a bunch of boilerplate


Well, if ADA commonly infers the type of loopvariables, we can lay that illusion to rest.

No, it means inference is much stricter than you believe







And that is one of the big issues with this. The compiler can only do best guess, and it sometimes will go wrong.

"Not a problem", I was told. In those cases I can still declare the loop var:
Code: Pascal  [Select]
  1. var i: qword;
  2. ...
  3. for i := OldCount to Count - 1 do // at this point, it is guaranteed that count will be  >=1
  4. ...
qword is needed because count could be a very large value ( >high(int64) ). And yes, this can happen, e.g. with sparse lists, or if values are calculated rather than stored.


A list of more than high(int64) elements... How often do you even have one of those lying around?


Anyways, the compiler should detect that both sides are QWord and promote them to a signed type. Now, the signed version of a QWord is not int64, it is int65 !


No issue at all.



Loop variables are variables too, they are important too, just as much as any other. (If they were not, that would imply, that the entire loop was not important, and leave the question why I did write the loop at all)


They are not important, if they are only used as index inside the loop. Then the variables are just an abbreviation for the actual data.

In functional programming languages you use map, and do not even have loop variables for it.
E.g.:

Code: [Select]
for i := 0 to stringlist.count - 1 do
  writeln(stringlist[i]);

would be

Code: [Select]
map(stringlist, writeln)

or

Code: [Select]
stringlist ! writeln(.)



in XQuery. No variable there. If you can write the same without a variable, the variable cannot be important
Title: Re: Ada style "for" loop counters
Post by: Martin_fr on January 18, 2016, 03:31:06 pm
Anyways, the compiler should detect that both sides are QWord and promote them to a signed type. Now, the signed version of a QWord is not int64, it is int65 !
There is not an int65. Of course it is possible to create one. But the computation overhead, and that in a potentially big loop. talk about de-optimizing the code.
Quote

Loop variables are variables too, they are important too, just as much as any other. (If they were not, that would imply, that the entire loop was not important, and leave the question why I did write the loop at all)

They are not important, if they are only used as index inside the loop. Then the variables are just an abbreviation for the actual data.
"variables are just an abbreviation for the actual data"
How does that differ to none loop variables?

Quote
In functional programming languages you use map, and do not even have loop variables for it.
E.g.:

Code: [Select]
for i := 0 to stringlist.count - 1 do
  writeln(stringlist[i]);

would be

Code: [Select]
map(stringlist, writeln)

Actually, in the above "writeln" is simple a pointer to a procedure, that is declared elsewhere.

"map" is a function (it may be intrinsic, but that does not change anything), inside which you loop over the list, and for that loop there is a loop variable.

That is exactly what I wrote. You can put the loop in a procedure of its own. That works well in current fpc too. (except you cant do @writeln, to get a reference to that procedure).

You are comparing apples and oranges. map has nothing to do with the presence or declaration of the loop var, it simple has something to do with putting the loop into another procedure.






off topic
Quote
In functional programming languages
map exists in OO style too.
Also pascal fully supports functional programming too.

"map" has nothing todo with functional programming.

You could have Tstringlist.map(eventProc) // that is OO
Title: Re: Ada style "for" loop counters
Post by: garlar27 on January 18, 2016, 05:20:44 pm
Sometimes it looks like they're trolling with that ADA, JAVA and C-ish things  :-\  :-\  :-\

When I have to program in JAVA, I need to see and to think diferent in order to make things work.
Do I miss the simple and straight forward Pascal's ways? Hell yes!!! But my pascalish way of doing things won't help. Even if they change the language to make me feel more comfortable.

Programming languages influence each other in some way for instance "try except", "try finally" has born in Delphi and now you can find it almost anywhere ad now are people who would like the way JAVA implement it (try except finaly) were implemented in FPC specially if internally it use the same "sandbox" for the except and finaly part instead of one inside the other. The same with variables with international characters like "Üáèñ_北京".

But add "words" from another language is one thing, but implements it grammar is one very diferent. Is like to use japanese grammar and english words and say "I speak english", or use english grammar with japanese words and pretend that every japanese understand what are you saying!!! It just won't work!!!
Title: Re: Ada style "for" loop counters
Post by: AlanTheBeast on January 18, 2016, 07:20:45 pm
    Readability of the vars section: focus on things that are important/relevant
And this has bothered me all the time. How does one determine the importance of a variable?

My code doesn't have unimportant or less important variables.
Loop variables are variables too, they are important too, just as much as any other. (If they were not, that would imply, that the entire loop was not important, and leave the question why I did write the loop at all)

If anything (not just loops) is not or less relevant to the current procedure, then it should be placed into its own procedure (where it then will be relevant). And I should call the procedure, rather than inlining the code.

So really the only reason not to have a variable in the var block, is because the code using it should not be in the code block (of this procedure) either. But hey, that is already supported.

All variables that do something in the code are equally important since the program would not otherwise compile.  But that is not the issue at all.

Loop control variable types are often, even very often in the case of math, not important wrt to understanding the code.  My own code is deluged with variables i,j,k,m,n,p,q that I know are not likely to be anything else and simply reading the code confirms this.  (though P, Q (coded in upper case) usually mean a pointer - but that's my quirk). 

I've written in the past that where the loop control variable is important to the understanding of the code, then by all means, declare it and describe it.  This proposal does not remove the ability to declare.

However, especially in things related to math, control variables are often not important at all from a declaration POV and do not really need declaration and they do not need to exist in scope except during the loop in question.  Indeed, where there may be the temptation to use the last value of a loop control value after the loop, such would remove this not recommended practice.

Finally (just to belabour the point) this is something Ada's (very strong type language) designers recognized.  Why would the most severe language allow this?  Because it's recognized as a clear intent to loop control and it is safe.
Title: Re: Ada style "for" loop counters
Post by: BeniBela on January 18, 2016, 07:21:19 pm

When I have to program in JAVA, I need to see and to think diferent in order to make things work.
Do I miss the simple and straight forward Pascal's ways? Hell yes!!! But my pascalish way of doing things won't help. Even if they change the language to make me feel more comfortable.

Always change the language!

Java user are ahead there. Since Java is such a piece of crap, they changed it and called it Scala. That one is much better. (Sadly they were inspired by C++ and now it compiles way too slowly)

Title: Re: Ada style "for" loop counters
Post by: Martin_fr on January 18, 2016, 07:52:25 pm
My own code is deluged with variables i,j,k,m,n,p,q
So is my code, but they all are important. After all they (usually / see below) get accessed inside the loop, that must mean they are needed.

Of course they (most of them) are only important inside the loop. But then many other local variables in many procedures I have seen, are only used in some part of the procedure. (and yet they get declared on top for the entire procedure. That just happen to be how pascal works).


There is one case. But for that, omitting declaration is not the solution either.
If the loop variable is not used at all.

Example: servers usually store the hash of a password only. To make the hashing more time consuming, and harden against brute force (if the hashes get stolen), they store the hash of the hash of the hash of the hash....

So you execute the code in the loop 100 times. But never access (not even read) the loop counter.

In that case the solution would be a loop that does not take a variable.
Code: Pascal  [Select]
  1. loop 100 times do x = crypt(x);
Title: Re: Ada style "for" loop counters
Post by: BeniBela on January 18, 2016, 07:55:27 pm
There is one case. But for that, omitting declaration is not the solution either.
If the loop variable is not used at all.

Example: servers usually store the hash of a password only. To make the hashing more time consuming, and harden against brute force (if the hashes get stolen), they store the hash of the hash of the hash of the hash....

So you execute the code in the loop 100 times. But never access (not even read) the loop counter.

In that case the solution would be a loop that does not take a variable.
Code: Pascal  [Select]
  1. loop 100 times do x = crypt(x);

That looks awesome!

Now you are getting it  ;)

But x := would be more Pascalish
Title: Re: Ada style "for" loop counters
Post by: Martin_fr on January 18, 2016, 07:56:21 pm
The missing : in := was a typo

Code: Pascal  [Select]
  1. Now you are getting it
But this is different. There is no variable.

"x"  is not the loop var, "x"  could be a string, an object, anything.

Also note: there is no upper and lower bound. Since inside the loop, there is on access to the "counter" or "iterator", that means there is on need for a value (and hence also not for a variable).
Title: Re: Ada style "for" loop counters
Post by: Martin_fr on January 18, 2016, 08:13:04 pm
And about the "ada is more strictly typed".

Well maybe, but what has that got to do with the "not explicitly declaring" of the loop var?

The loop var is still typed. In the sense that a type is decided at compile time. if you loop "for a := 1 to 10", you still can NOT do "if a = true then".

So nothing changes about the variable being typed. Hence it does not matter how "strictly typed" ADA is or is not, or whatever.


But (explicit) declaration does more than just setting a type.

1) it does give the human reader an overview of which identifiers are already used. And for that to be of any use, the list must be complete.
That is declaration (of all) variables *improves* readability

2) By (explicitly) setting the type of the variable, independent of the type of the value that later gets assigned (the bounds of the loop), it allows for cross verification and additional error detection.
After all, if your statement about "importance" would apply, the many other variables may be deemed unimportant too. A flag to carry a test result forward "a := true", can have its type detected by the compiler too, all you reasons for not needing to declare "a" apply to this too. So then all declarations would become optional. (And that is simple not what pascal is about, maybe ADA is, but ADA is not pascal)

Maybe more...
Title: Re: Ada style "for" loop counters
Post by: ykot on January 18, 2016, 08:14:40 pm
Loop control variable types are often, even very often in the case of math, not important wrt to understanding the code.  My own code is deluged with variables i,j,k,m,n,p,q that I know are not likely to be anything else and simply reading the code confirms this.  (though P, Q (coded in upper case) usually mean a pointer - but that's my quirk). 
From what you are saying (and suggesting), it looks like you have issues in your own code. As a general rule of the thumb, if you have method that is larger than your code view screen, you should refactor it into multiple smaller methods. Same applies to local variables - if your declaration becomes clogged with them, it's time to refactor the method into few multiple ones. Also, you seem to use poor and inconsistent naming scheme mixing upper and lower 1-letter variables - even if you work alone on your code, for sake of maintenance you should use more context-sensitive names. For instance, although "I" is typically used as general-purpose counter, since you have many such variables, you might want it to be more descriptive, i.e. ElementCount or ItemIndex. In some cases, you might want to learn how enumerators work, so you can implement them for your own objects/types - this will further help code maintenance.

The "hack" that was proposed here to avoid declaring variables used in FOR loop counters is actually counter-intuitive both for the developer and the compiler. Just because a language X has certain "syntax trick" and even if such language in some way "looks similar" to Pascal syntax, is under no circumstances a good/sufficient justification by itself to introduce this "syntax trick" to another language.

Martin_fr is absolutely right that whatever optional feature (though I myself don't consider what's discussed here a "feature", but more like a dirty code trick) is implemented, at one point or another some people will start using it, which eventually will affect much larger developer audiences in terms of development, extensibility and maintenance (again, as Martin_fr accurately described), contributing to Pascal language becoming less readable overall.

The suggestion described here would be a perfect example of an Anti-pattern (https://en.wikipedia.org/wiki/Anti-pattern). Hopefully, no FPC developer would be crazy enough to even think of introducing such syntax hack into the language.
Title: Re: Ada style "for" loop counters
Post by: BeniBela on January 18, 2016, 08:52:38 pm

 , if you have method that is larger than your code view screen, you should

get a bigger view screen!! (http://tng.trekcore.com/bluray/images/120_058_BreakDown8.jpg)
Title: Re: Ada style "for" loop counters
Post by: BeniBela on January 28, 2016, 09:26:28 pm
I just found this in my code

Code: [Select]
  var n: IXQValue;
  begin
     for n in something do
       for n in n.getsomething do
           ...
   end;

two nested loops with the same identifier

does not compile in 3.x, but 2.x accepts it without issue and it even works.

This is what you get, when you try to minimize the used variables, because the declarations are so cumbersome
Title: Re: Ada style "for" loop counters
Post by: AlanTheBeast on February 13, 2016, 05:07:00 pm
Loop control variable types are often, even very often in the case of math, not important wrt to understanding the code.  My own code is deluged with variables i,j,k,m,n,p,q that I know are not likely to be anything else and simply reading the code confirms this.  (though P, Q (coded in upper case) usually mean a pointer - but that's my quirk). 
From what you are saying (and suggesting), it looks like you have issues in your own code. As a general rule of the thumb, if you have method that is larger than your code view screen, you should refactor it into multiple smaller methods. Same applies to local variables - if your declaration becomes clogged with them, it's time to refactor the method into few multiple ones. Also, you seem to use poor and inconsistent naming scheme mixing upper and lower 1-letter variables - even if you work alone on your code, for sake of maintenance you should use more context-sensitive names. For instance, although "I" is typically used as general-purpose counter, since you have many such variables, you might want it to be more descriptive, i.e. ElementCount or ItemIndex. In some cases, you might want to learn how enumerators work, so you can implement them for your own objects/types - this will further help code maintenance.

The "hack" that was proposed here to avoid declaring variables used in FOR loop counters is actually counter-intuitive both for the developer and the compiler. Just because a language X has certain "syntax trick" and even if such language in some way "looks similar" to Pascal syntax, is under no circumstances a good/sufficient justification by itself to introduce this "syntax trick" to another language.

Martin_fr is absolutely right that whatever optional feature (though I myself don't consider what's discussed here a "feature", but more like a dirty code trick) is implemented, at one point or another some people will start using it, which eventually will affect much larger developer audiences in terms of development, extensibility and maintenance (again, as Martin_fr accurately described), contributing to Pascal language becoming less readable overall.


Thanks for yet another tired defense that's been quoted before.  I can only say as a very longtime Pascal programmer that I'm saddened at the defense over something so simple and obvious for simplification - something the much more safety-critical, strong- readabilty, long term code maintenance oriented Ada did from the start - and it was largely influenced by Pascal's strong typing model and took it further in all directions - except this one - for very good reason:  declaring such vars DOES NOT ACTUALLY HELP CODE READABILTY, MAINTENANCE OR SAFETY.

It is not a "hack" and it is not "dirty code trick" (high school debating of the US negative-label style is really unbecoming of you!)

Well I'm done, to everyone's relief I expect.

(Sorry I've been away for a bit and on other things).
Title: Re: Ada style "for" loop counters
Post by: BeniBela on February 14, 2016, 12:25:13 am

Well I'm done, to everyone's relief I expect.

 :o

We will miss you
Title: Re: Ada style "for" loop counters
Post by: Ñuño_Martínez on February 15, 2016, 06:07:04 pm
If you like ADA, use ADA. 8)
Title: Re: Ada style "for" loop counters
Post by: BeniBela on December 18, 2016, 01:53:21 pm
And now my program crashed again, because there are loop-scoped variables.

I had  a function like

Code: Pascal  [Select]
  1. var i: integer;
  2. ...
  3. for i := 0 to high(anArray) do
  4.    dosomething(anArray[i], anotherArray[i]);
  5.  
  6. dosomething(somethingElse, anotherArray[i]);
  7.  

copy/pasted dosomething. The value of i seems to have changed between fpc versions.

If it was

Code: Pascal  [Select]
  1. for var i := 0 to high(anArray) do
  2.    dosomething(anArray[i], anotherArray[i]);
  3. ...
  4.  

it would have been an obvious compile error.

Now it does not even give a hint.
Title: Re: Ada style "for" loop counters
Post by: zeljko on December 18, 2016, 02:30:45 pm
Never use for variable after the loop.

This is bad:
  var i: integer;
begin
  for i := 0 to high(anArray) do
    dosomething(anArray, anotherArray);
  dosomething(somethingElse, anotherArray);
end;

This is bad:
  var i,x: integer;
begin
  x := -1;
  for i := 0 to high(anArray) do
  begin
    dosomething(anArray, anotherArray);
    x := i;
  end;
  if x >= 0 then
    dosomething(somethingElse, anotherArray
  • );

end;
Title: Re: Ada style "for" loop counters
Post by: Thaddy on December 18, 2016, 03:15:35 pm
Now it does not even give a hint.
Why a hint?
You instructed to compiler to -- from? Why would the index  be valid after that? It is not an index anymore.
Title: Re: Ada style "for" loop counters
Post by: Leledumbo on December 18, 2016, 03:26:52 pm
And now my program crashed again, because there are loop-scoped variables.

I had  a function like
...
copy/pasted dosomething. The value of i seems to have changed between fpc versions.
Page 57 (http://www.pascal-central.com/docs/iso7185.pdf):
"After a for-statement is executed, other than being left by a goto-statement, the control-variable shall be undefined."
It was and is designed that way, it never changes. It's also never a problem unless you think that all repetitive statements are equal, i.e. transformable from one to another within the same type value boundary, because they are not in Pascal world.
Title: Re: Ada style "for" loop counters
Post by: marcov on December 18, 2016, 03:57:10 pm
Note that the compiler "could" see that a variable is read that is not defined at that point and emit a warning.

The compiler is not perfect and certainly could have some polishing here and there. But not every little flaw means that the syntax should be blamed and radically changed.
Title: Re: Ada style "for" loop counters
Post by: BeniBela on December 18, 2016, 06:22:35 pm
Why would the index  be valid after that? It is not an index anymore.

That is why fpc should not compile it happily

Note that the compiler "could"should see that a variable is read that is not defined at that point and emit a warning.

 

ftfy
Title: Re: Ada style "for" loop counters
Post by: marcov on December 18, 2016, 06:50:06 pm
Note that the compiler "could"should see that a variable is read that is not defined at that point and emit a warning.
ftfy

Well, everybody says that about any problem they have. But if you want to hurry up, start creating a patch.
Title: Re: Ada style "for" loop counters
Post by: BeniBela on December 19, 2016, 08:33:01 pm
When there are ada-like patches they are not merged anyways (like the ifthen intrinsic debacle)...
Title: Re: Ada style "for" loop counters
Post by: marcov on December 19, 2016, 10:32:19 pm
When there are ada-like patches they are not merged anyways (like the ifthen intrinsic debacle)...

I meant a patch to add the warning, not the Ada syntax (which I think is pointless to introduce that now, it will only cause more confusion and dialectitis)
Title: Re: Ada style "for" loop counters
Post by: z505 on May 12, 2017, 11:40:45 am
If you like ADA, use ADA. 8)

Or you can use GoLang which allows you to use variables automagically without declaring them first...

My experience with GoLang however tells me that GoLang code is much easier to write, than it is to read. Whenever I am looking at someone's golang code there are virtually no declarations of local variables anywhere (well there are some in rare occasions) and this makes the code much harder to read because you have no clue what type a variable is, for example when a function returns a value.. You have to go to the documentation to see what the function returns as a type, because it's not declared in the program.

This is a double edged sword. Makes programs easier to write, but harder to read.

But for local loop counters, everyone knows what the loop counter "i" is supposed to be for so I can see your point about not declaring it, but I find this such a small issue in programming that ... "is it worth the hassle of implementing such a small feature that makes programming maybe less than 0.000001 percent easier on users" when in fact like Marcov said, a patch could be added to the compiler to warn/forbid people from using "i" loop counters again in the same procedure further down?
Title: Re: Ada style "for" loop counters
Post by: Leledumbo on May 13, 2017, 08:12:19 pm
[My experience with GoLang however tells me that GoLang code is much easier to write, than it is to read. Whenever I am looking at someone's golang code there are virtually no declarations of local variables anywhere (well there are some in rare occasions) and this makes the code much harder to read because you have no clue what type a variable is, for example when a function returns a value.. You have to go to the documentation to see what the function returns as a type, because it's not declared in the program.
Add "no idea what interfaces this struct implement" to the list.
Title: Re: Ada style "for" loop counters
Post by: Thaddy on May 13, 2017, 09:48:06 pm
But for local loop counters, everyone knows what the loop counter "i" is supposed to be for so I can see your point about not declaring it
Well, if the compiler knows about i and about the scope you can even skip it's declaration completely by using for in do... Which implies i... 8-)