For/Next Loop with Step doesn't excute properly

Just starting out? Need help? Post your questions and find answers here.
User avatar
Demivec
Addict
Addict
Posts: 4260
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

For/Next Loop with Step doesn't excute properly

Post by Demivec »

PB Manual wrote:The For : Next function is used to create a loop within a program with the given parameters. At each loop the <variable> value is increased by a 1, (or of the "Step value" if a Step value is specified) and when the <variable> value is above the <expression2> value, the loop stop.
The following For/Next loops fail to execute even once even though the <variable> is not outside the range of the loop.

Code: Select all

Debug "loop start"
For x = 1 To 3 Step -2
  Debug "doesn't execute"
Next
Debug "loop over"

Debug "loop start"
For x = 3 To 1 Step 2
  Debug "doesn't execute"
Next
Debug "loop over"
The loop <variable> is checked incorrectly because of the sign of the Step value. In the first instance the <variable> is checked to see if it is less than 3 (because of Step -2).

If this is the desired behavior the manual should at least be updated.
Last edited by Demivec on Thu May 14, 2009 6:12 pm, edited 1 time in total.
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Re: For/Next Loop with Step doesn't excute properly

Post by PB »

You're coding them incorrectly. In the first example, you want to count up
(from 1 to 3) but the step value is negative, meaning that it's counting down
instead. So it's no surprise that the loop doesn't occur. The opposite happens
in your second example. No bug as far as I can see.
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post by Kaeru Gaman »

this is on purpose.

as I learned over 25 years ago, a For-Loop is always executed at least once,
because it's an end-controlled loop like Repeat and not head-controlled like While.

the description in the Help does not contradict this old definition.

Demivec just created an example that does not match this definition.


the conclusion is:
either the behaviour or the description should be changed.

I vote for correcting the description.
Last edited by Kaeru Gaman on Thu May 14, 2009 3:20 pm, edited 1 time in total.
oh... and have a nice day.
User avatar
DoubleDutch
Addict
Addict
Posts: 3220
Joined: Thu Aug 07, 2003 7:01 pm
Location: United Kingdom
Contact:

Post by DoubleDutch »

I think what happens is correct too. So please just change the description.
https://deluxepixel.com <- My Business website
https://reportcomplete.com <- School end of term reports system
freak
PureBasic Team
PureBasic Team
Posts: 5940
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Post by freak »

The behavior is correct. The docs are also correct, they only do not mention the possibility for a negative step.

Take the second example:
The docs say that the loop stops as soon as the counter is greater than the second expression. Since this is true from the beginning, the loop never executes.

Its the same in the other direction.
quidquid Latine dictum sit altum videtur
User avatar
Demivec
Addict
Addict
Posts: 4260
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Post by Demivec »

freak wrote:The behavior is correct. The docs are also correct, they only do not mention the possibility for a negative step.

Take the second example:
The docs say that the loop stops as soon as the counter is greater than the second expression. Since this is true from the beginning, the loop never executes.

Its the same in the other direction.
It would be helpful to have some small notation provided in the manual for clarity. Something to the effect that "If the Step value is negative the loop will exit when the <variable> is less than expression2. If the Step value is positive the loop will exit when the <variable> is greater than expression2."
Last edited by Demivec on Thu May 14, 2009 6:26 pm, edited 1 time in total.
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post by Kaeru Gaman »

... and this is the reason why a For-Loop was defined as bottom-controlled and executing at least once, back in the years I started, shortly after iceage...

the feature that the loop wouldn't execute at all with a step-value that has the opposite sign than the interval defined by start/stop values, is some new and additional feature... somehow...
oh... and have a nice day.
User avatar
Demivec
Addict
Addict
Posts: 4260
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Post by Demivec »

Kaeru Gaman wrote:... and this is the reason why a For-Loop was defined as bottom-controlled and executing at least once, back in the years I started, shortly after iceage...

the feature that the loop wouldn't execute at all with a step-value that has the opposite sign than the interval defined by start/stop values, is some new and additional feature... somehow...
For fun I ran some emulator's for 3 old computer systems of the 1980's era and a corresponding version of Basic. They each executed the example loops once. I've gotten use to the way it functions in PB. That's why I simply would like it documented.
freak
PureBasic Team
PureBasic Team
Posts: 5940
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Post by freak »

Kaeru Gaman wrote:... and this is the reason why a For-Loop was defined as bottom-controlled and executing at least once, back in the years I started, shortly after iceage...

the feature that the loop wouldn't execute at all with a step-value that has the opposite sign than the interval defined by start/stop values, is some new and additional feature... somehow...
May be other languages did it this way but it doesn't really make sense to me. Why would you want to execute the loop when you are already past your end-condition? That would make for some hard to find bugs if you don't expect that.

Its like telling someone to "walk up the stairs from step 10 to step 5". Its just not possible to do that so why would "walking up 1 step" be the correct response? Imho the only correct thing is to do nothing at all, which PB is doing.
quidquid Latine dictum sit altum videtur
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Post by ts-soft »

As freak says:

Code: Select all

For I = 1 To CountGadgetItems(bla)
  DoWith(I)
Next
The loop should never executed if no items.
This make most sense for me, and not a step to 0
PureBasic 5.73 | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.
Image
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post by Kaeru Gaman »

staying with your example, a For loop would mean
"do something, e.g. clap your hands, on each step, then walk on to the next step"
so, when you start on step 10, should go to step 5, and have the instruction to alter by +1 every time,
why shouldn't you FIRST clap your hands and only THEN realize that you could not reach your End by using the given STEP?

during the FIRST iteration, you are definitely not "past your end-condition".
you are still on the starting value, so you should execute whatever you are instructed to.

the definition of a For-Loop is "do something with the actual value and THEN alter the variable by Stepvalue and check if end-condition is reached."


I now that the discussion is rather academic.


PS:
> The loop should never executed if no items.
well, nice example.
... but this is a quite special use of a For-Loop, and back in the 80ies you would have produced an Error when the list was empty, just because a For-Loop was executed at least once.
oh... and have a nice day.
User avatar
djes
Addict
Addict
Posts: 1806
Joined: Sat Feb 19, 2005 2:46 pm
Location: Pas-de-Calais, France

Post by djes »

If I remember correctly, in QuickBASIC there was a flag or a compiler directive to change this behaviour, as the two are corrects. This is one of the classic BASIC debate subject.
User avatar
DoubleDutch
Addict
Addict
Posts: 3220
Joined: Thu Aug 07, 2003 7:01 pm
Location: United Kingdom
Contact:

Post by DoubleDutch »

If For Next executed once - then what about ForEach? It's obvious that it should not execute.
https://deluxepixel.com <- My Business website
https://reportcomplete.com <- School end of term reports system
Mahan
User
User
Posts: 35
Joined: Sun Jan 25, 2009 10:12 am
Location: Sweden

Post by Mahan »

Even though I'm a fairly new PureBasic user I must give my support for the current behavior.

I've programmed an awful amount of languages and scripts and this is by far the most common behavior i.e:

Code: Select all

for a = b to c step d
equals (when incremental):

Code: Select all

a=b ; initial state
while a <= c ; check if "go" for another iteration

  a = a + d ; increment
wend
This of course means that if b > c, loop-body will never happen even once.

Maybe it's a matter of habit but I almost never write repeat..until loops anymore. I only use while..wend, for..next and foreach..next loops.

It's probably because a while..wend type loop are very easy to rig for 1 single forced run-through, and repeat..until loops imply 1 forced run-through, and I simply choose to use the one i can use every time regardless.
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post by Trond »

For loops are not end controlled, and shouldn't be, since the condition is listed at the beginning. It makes sense to check for the condition where the condition is actually written in the code.

Code: Select all

For i = 1 to 40 ; since the condition is written here, evaluate it here
Next

While i <= 40 ; since the condition is written here, evaluate it here
Wend

Repeat
Until i > 40 ; since the condition is written here, evaluate it here
It makes no sense for the compiler to move the condition code to the bottom.

Negative step values are tricky, I usually code them as While loops instead, as it's much more clear what's going on then.
Post Reply