Recent

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

Leledumbo

  • Hero Member
  • *****
  • Posts: 8111
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: Ada style "for" loop counters
« Reply #60 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.

Martin_fr

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

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 7499
Re: Ada style "for" loop counters
« Reply #62 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.

AlanTheBeast

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

... in Pascal?  I tried compiling one a few minutes ago and it certainly did not work.

AlanTheBeast

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

AlanTheBeast

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

AlanTheBeast

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

AlanTheBeast

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

AlanTheBeast

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


« Last Edit: January 18, 2016, 01:32:37 am by AlanTheBeast »

taazz

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

... 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.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

AlanTheBeast

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

... 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).

bylaardt

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

FTurtle

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

FTurtle

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

Martin_fr

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