Recent

Author Topic: Ada style "for" loop counters  (Read 42690 times)

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 5705
    • wiki
Re: Ada style "for" loop counters
« Reply #75 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.

BeniBela

  • Hero Member
  • *****
  • Posts: 684
    • homepage
Re: Ada style "for" loop counters
« Reply #76 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.


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

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 5705
    • wiki
Re: Ada style "for" loop counters
« Reply #77 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
« Last Edit: January 18, 2016, 03:37:09 pm by Martin_fr »

garlar27

  • Hero Member
  • *****
  • Posts: 618
Re: Ada style "for" loop counters
« Reply #78 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!!!

AlanTheBeast

  • Jr. Member
  • **
  • Posts: 50
Re: Ada style "for" loop counters
« Reply #79 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.

BeniBela

  • Hero Member
  • *****
  • Posts: 684
    • homepage
Re: Ada style "for" loop counters
« Reply #80 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)


Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 5705
    • wiki
Re: Ada style "for" loop counters
« Reply #81 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);

BeniBela

  • Hero Member
  • *****
  • Posts: 684
    • homepage
Re: Ada style "for" loop counters
« Reply #82 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

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 5705
    • wiki
Re: Ada style "for" loop counters
« Reply #83 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).
« Last Edit: January 18, 2016, 08:17:17 pm by Martin_fr »

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 5705
    • wiki
Re: Ada style "for" loop counters
« Reply #84 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...

ykot

  • Full Member
  • ***
  • Posts: 141
Re: Ada style "for" loop counters
« Reply #85 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. Hopefully, no FPC developer would be crazy enough to even think of introducing such syntax hack into the language.

BeniBela

  • Hero Member
  • *****
  • Posts: 684
    • homepage
Re: Ada style "for" loop counters
« Reply #86 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!!

BeniBela

  • Hero Member
  • *****
  • Posts: 684
    • homepage
Re: Ada style "for" loop counters
« Reply #87 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

AlanTheBeast

  • Jr. Member
  • **
  • Posts: 50
Re: Ada style "for" loop counters
« Reply #88 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).

BeniBela

  • Hero Member
  • *****
  • Posts: 684
    • homepage
Re: Ada style "for" loop counters
« Reply #89 on: February 14, 2016, 12:25:13 am »

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

 :o

We will miss you