A STEP forward into the future.

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
User avatar
Demivec
Addict
Addict
Posts: 4258
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Post by Demivec »

Here's another version with a slight twist to Kaeru's. This one handles "single" loops of just one execution.

Code: Select all

;counting loop with variable Step value
Procedure loopy(aStart,aStop,aStep)
  Debug "Cust: " + Str(aStart) + " To " + Str(aStop) + " Step " + Str(aStep)
  If (aStep > 0 And aStop < aStart) Or (aStep < 0 And aStop > aStart) Or aStep = 0
    ProcedureReturn aStart
  EndIf 
  
  Protected aLoop = aStart
  Repeat
    ;loop code performed here
    Debug aLoop
    
    ;end of loop routines
    aLoop + aStep
    If aStep < 0
      If aLoop < aStop
        Break
      EndIf
    Else
      If aLoop > aStop
        Break
      EndIf 
    EndIf 
  ForEver
  ProcedureReturn aLoop
EndProcedure 

;standard For/Next with nonvariable Step
Macro loopy2(aStart,aStop,aStep)
  Debug "For: " + Str(aStart) + " To " + Str(aStop) + " Step " + Str(aStep)
  For aLoop = aStart To aStop Step aStep
    Debug aLoop
  Next
EndMacro

;counting loop that uses floats
Procedure loopy3(aStart.f,aStop.f,aStep.f) 
  Debug "Float: " + StrF(aStart,2) + " To " + StrF(aStop,2) + " Step " + StrF(aStep,2)
  If (aStep > 0 And aStop < aStart) Or (aStep < 0 And aStop > aStart) Or aStep = 0
    ProcedureReturn aStart
  EndIf 
  
  Protected aLoop.f = aStart
  Repeat
    ;loop code performed here
    Debug StrF(aLoop,2)
    
    ;end of loop routines
    aLoop + aStep
    If aStep < 0
      If aLoop < aStop
        Break
      EndIf
    Else
      If aLoop > aStop
        Break
      EndIf 
    EndIf 
  ForEver
  ProcedureReturn aLoop
EndProcedure 

;test each possible loop with a selection of values
loopy(5, 60, 9)
loopy2(5, 60, 9)
loopy(5, 60, -9)
loopy2(5, 60, -9)
loopy(60, 5, 9)
loopy2(60, 5, 9)
loopy(60, 5, -9)
loopy2(60, 5, -9)
loopy(-5, -60, 9)
loopy2(-5, -60, 9)
loopy(-5, -60, -9)
loopy2(-5, -60, -9)
loopy(-60, -5, 9)
loopy2(-60, -5, 9)
loopy(-60, -5, -9)
loopy2(-60, -5, -9)
loopy(5, 5, 9)
loopy2(5, 5, 9)
loopy(5, 5, -9)
loopy2(5, 5, -9)
loopy(-5, -5, 9)
loopy2(-5, -5, 9)
loopy(-5, -5, -9)
loopy2(-5, -5, -9)
Debug ""
loopy3(5.2, 60.7, 9.3)
loopy3(5.2, 60.7, -9.3)
loopy3(60.7, 5.2, 9.3)
loopy3(60.7, 5.2, -9.3)
loopy3(-5.2, -60.7, 9.3)
loopy3(-5.2, -60.7, -9.3)
loopy3(-60.7, -5.2, 9.3)
loopy3(-60.7, -5.2, -9.3)
loopy3(5.2, 5.2, 9.3)
loopy3(5.2, 5.2, -9.3)
loopy3(-5.2, -5.2, 9.3)
loopy3(-5.2, -5.2, -9.3)
I've included a complete (almost) set of tests to demonstrate it functions well (for looping, maybe not for speed). The tests include a version that operates with integers and one that operates with floats. The standard For/Next is included also for comparison.

It is noted that if some slightly sloppy programming is not contrary to your style you can just modify the For/Next loop variable incrementing/decrementing it according to your needs. Even so, this has at least two noteworthy limitations: you have to do a special check to make sure the loop's ending conditions are not met before it starts (depends on the sign of the Step), and you are still limited to using integers (no float values for the Step).
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post by Kaeru Gaman »

I had another idea for a Modification:

Code: Select all

LoopCount = LoopStart
Repeat

;********************
;** In-Loop Action **
  Debug LoopCount
;********************

  LoopCount + LoopStep
  If LoopStart < LoopStop
    If LoopCount > LoopStop Or LoopCount < LoopStart
      LoopEnd = #True
    EndIf
  Else
    If LoopCount < LoopStop Or LoopCount > LoopStart
      LoopEnd = #True
    EndIf
  EndIf
Until LoopEnd
this should allow ANY variations, even Floats for each Value and changing of the StepValue while running, even changing of the sign.
(sure, there are certain conditions where the loop will never end.)
with this, this is MORE than any Variation of a For-Loop will allow.


@topic
In fact, I wouldn't mind if a new additional For Loop would be implemented...

But I really don't want any detail of the existing For-Loop to be changed, I don't want it to lose a sincle cycle.
oh... and have a nice day.
akj
Enthusiast
Enthusiast
Posts: 668
Joined: Mon Jun 09, 2003 10:08 pm
Location: Nottingham

Post by akj »

@Demivec:

You have missed the point with your macro suggestion.
I accept that this works:

Code: Select all

loopy2(5, 60, 9)
but what I'm trying to do is more akin to

Code: Select all

y = 6 + 3
loopy2(5, 60, y)
But this fails to work.


@KaeruGaman:
You say
I don't want it to lose a single cycle.
But the compiler will detect when the Step value is a constant and will generate code identical to that produced currently and absolutely no speed will be lost. It's only when the compiler detects that Step is a variable or expression, that it will generate more complex code.


After seeing the suggested For/Step/Next emulations, I still think that

Code: Select all

For LoopCount = LoopStart to LoopEnd Step LoopCount
  . . .
Next
is infinitely preferable to something like

Code: Select all

LoopCount = LoopStart
LoopEnd = #False
Repeat
  . . .
  LoopCount + LoopStep
  If LoopStart < LoopStop
    If LoopCount > LoopStop Or LoopCount < LoopStart
      LoopEnd = #True
    EndIf
  Else
    If LoopCount < LoopStop Or LoopCount > LoopStart
      LoopEnd = #True
    EndIf
  EndIf
Until LoopEnd
And as it happens the latter emulation code (suggested by KaeruGaman) is flawed as it does not correctly implement the equivalent of

Code: Select all

For x = 5 To 60 Step -9
This is because the body of the emulation loop is evaluated at least once (due to the Repeat statement), but it should not be evaluated at all.
Anthony Jordan
User avatar
Demivec
Addict
Addict
Posts: 4258
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Post by Demivec »

akj wrote:@Demivec:

You have missed the point with your macro suggestion.
I accept that this works:

Code: Select all

loopy2(5, 60, 9)
but what I'm trying to do is more akin to

Code: Select all

y = 6 + 3
loopy2(5, 60, y)
But this fails to work.
@akj: I did get your point. I didn't use the macro to solve the problem, I used the macro to setup a For/Next loop with the same start/stop/step values the only way it can be done currently (which is limited). In other words the macro demonstrates everything you say is the problem. Since a variable step isn't permitted I couldn't do it with a procedure (see pdwyer's comments, and my solution). The macro wasn't the solution, it was to show the solution resulted in a loop that functioned identically to a corresponding For/Next loop that had a constant Step. The solution exceeds in that it does everything the For/Next loop does and it has a variable Step. As mentioned previously the solution has not been speed tested for comparison.
@KaeruGaman:
You say
I don't want it to lose a single cycle.
But the compiler will detect when the Step value is a constant and will generate code identical to that produced currently and absolutely no speed will be lost. It's only when the compiler detects that Step is a variable or expression, that it will generate more complex code.


After seeing the suggested For/Step/Next emulations, I still think that

Code: Select all

For LoopCount = LoopStart to LoopEnd Step LoopCount
  . . .
Next
is infinitely preferable to something like

Code: Select all

LoopCount = LoopStart
LoopEnd = #False
Repeat
  . . .
  LoopCount + LoopStep
  If LoopStart < LoopStop
    If LoopCount > LoopStop Or LoopCount < LoopStart
      LoopEnd = #True
    EndIf
  Else
    If LoopCount < LoopStop Or LoopCount > LoopStart
      LoopEnd = #True
    EndIf
  EndIf
Until LoopEnd
I used a procedure to demonstrate a working solution, it could also have been done with a macro or two. In this way it avoids the procedure call:

Code: Select all

;counting loop (w/variable Step value) setup routines
Macro BeginLoop(vLoop, aStart, aStop, aStep = 1) ;vLoop must be a variable, not a constant nor an expression
  vLoop = aStart
  If (aStep > 0 And aStop < aStart) Or (aStep < 0 And aStop > aStart) Or aStep = 0
  Else
    Repeat
      
EndMacro
    
;end of counting loop (w/variable Step) routines
Macro EndLoop(vLoop, aStart, aStop, aStep = 1) ;vLoop must be a variable, not a constant nor an expression
      vLoop + aStep
      If aStep < 0
        If vLoop < aStop
          Break
        EndIf
      Else
        If vLoop > aStop
          Break
        EndIf
      EndIf
    ForEver
  EndIf
EndMacro

Repeat
  Text$ = InputRequester("Loop values, Type [Enter] to exit", "Enter start,Stop, And Step (i.e. 5,60,9)","")
  If Text$=""
    Break
  EndIf
  
  b = Val(StringField(Text$,1,","))
  c = Val(StringField(Text$,2,","))
  d = Val(StringField(Text$,3,","))
  
  Debug "Loop: " + Str(b) + " To " + Str(c) + " Step " + Str(d)
  BeginLoop(a,b,c,d)
    Debug a
  EndLoop(a,b,c,d)
  Debug "----Loop end value: " + Str(a)
  
ForEver
Doing things this way you can also put one loop inside of another. I was going to post an example of that but I leave it as an exercise for the interested reader.

Notwistanding all the above, I agree with the feature request. It seems like it could be accomplished with compiling one of two different styles of loop depending on whether a variable step was used or not. :wink:
akj
Enthusiast
Enthusiast
Posts: 668
Joined: Mon Jun 09, 2003 10:08 pm
Location: Nottingham

Post by akj »

@Demivec:

Yes, sorry. I did misinterpret the purpose of the loopy2() macro, but on re-reading your post, I now understand what you had in mind.

I feel your BeginLoop() and EndLoop() macros are much closer to an acceptable solution and I will probably adopt them until For/Next supports Step expressions. Thanks.
Anthony Jordan
User avatar
Demivec
Addict
Addict
Posts: 4258
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Post by Demivec »

akj wrote:@Demivec:

Yes, sorry. I did misinterpret the purpose of the loopy2() macro, but on re-reading your post, I now understand what you had in mind.

I feel your BeginLoop() and EndLoop() macros are much closer to an acceptable solution and I will probably adopt them until For/Next supports Step expressions. Thanks.
Your welcome, I'm glad I could be of some help.
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post by Kaeru Gaman »

akj wrote:But the compiler will ...
the compiler will do what Fred teaches him to do,
and it will take a whole lot of work to change the implementation of some long established feature in four, five, six compiler versions,
and in a way that the result is reliable and durable.

ever heard the words "never change a running system"?

people don't say this of religion, but just of experience....
akj wrote:After seeing the suggested For/Step/Next emulations, I still think that
[code1]
is infinitely preferable to something like
[code2]
If you don't like the more code, built a macro out of it or set a code folding....
akj wrote:And as it happens the latter emulation code (suggested by KaeruGaman) is flawed as it does not correctly implement the equivalent of

Code: Select all

For x = 5 To 60 Step -9
This is because the body of the emulation loop is evaluated at least once (due to the Repeat statement), but it should not be evaluated at all.
by definition, no!
a For-Loop is defined to be executed at least once.
this is the way it was since I first touched BASIC, over 25 years ago.


as I already said, I do not mind implementing some more conveniant and flexible version of a For-Loop.
and as I also said, and you quoted, I do not want to lose a single cycle when using the variation we already have.
since we have no genie Image who creates us five new compilers by one wish,
every change of an established feature is a bloody big task.
oh... and have a nice day.
akj
Enthusiast
Enthusiast
Posts: 668
Joined: Mon Jun 09, 2003 10:08 pm
Location: Nottingham

Post by akj »

@Kaeru Gaman:

You say:
the compiler will do what Fred teaches him to do
and:
since we have no genie who creates us five new compilers by one wish
Please do not underestimate Fred's capabilities!



You also say:
by definition, no!
a For-Loop is defined to be executed at least once.
But this is not true in practice. I choose four Basic compilers at random and the documentation for each supports my assertion that under appropriate circumstances the For-Loop body will NOT be executed at all (PureBasic also works this way). The facts are here:
GW-Basic
www.antonis.de/qbebooks/gwbasman/fornext.html
"The body of the loop is skipped if the initial value of the loop times the sign of the step exceeds the final value times the sign of the step."
VisualBasic
msdn.microsoft.com/en-us/library/5z06z1kb.aspx
"Entry into the Loop: When execution of the For...Next loop begins, Visual Basic evaluates start, end, and step for the only time. It then assigns start to counter. Before it runs the statement block, it compares counter to end. If counter is already past the end value, the For loop terminates and control passes to the statement following the Next statement. Otherwise the statement block runs."
PowerBasic
http://www.powerbasic.com/support/help/ ... ements.htm
"The body of the loop is skipped altogether if the initial value of Counter is greater than stop (or, for a negative increment, if Counter is less than stop)."
FreeBasic
www.freebasic.net/wiki/wikka.php?wakka=KeyPgFornext
"If endvalue is less than startvalue then a negative stepvalue must be specified or the statement block will not execute at all, since startvalue compares greater than endvalue."

Finally you say:
If you don't like the more code, built a macro out of it
but there is no really good macro solution. The best that can be done is probably that achieved by Demivec's macro-pair BeginLoop() and EndLoop(), but I doubt whether he would claim it an ideal solution.
Anthony Jordan
User avatar
pdwyer
Addict
Addict
Posts: 2813
Joined: Tue May 08, 2007 1:27 pm
Location: Chiba, Japan

Post by pdwyer »

Give the guy a break Kaeru, he just making a request and it's been noted that others would not like it if it changes the current working with constants (which it might not)

This isn't a Saddam election, you don't have to beat him into retracting his request!

It's a legit request with a legit concern raised. Leave him alone, it's not a court of law
Paul Dwyer

“In nature, it’s not the strongest nor the most intelligent who survives. It’s the most adaptable to change” - Charles Darwin
“If you can't explain it to a six-year old you really don't understand it yourself.” - Albert Einstein
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post by Kaeru Gaman »

akj wrote:Please do not underestimate Fred's capabilities!
I don't underestimate Fred at all!

I just want everybody to remember that every change on the compilers means a lot of work for him, and that it's his decision if he wants to invest time and power in this task, since there are possibilities for each programmer to solve it a different way.

akj wrote:But this is not true in practice. I choose four Basic compilers at random and the documentation for each supports my assertion that under appropriate circumstances the For-Loop body will NOT be executed at all (PureBasic also works this way). The facts are here:...
interesting.
in fact, I did not bother with this detail of a For-Loop for a long time. *shrug*

sure it would be possible to change Demivec's code or mine in a way to solve ALL eventualities.

The more it should cover, the messier and uglier it gets, don't you think?

well... this exactly is the problem to implement it into the compiler.
the more waterproof you want it, the more complex it gets, and the more problems and bug-creating-coincidences arise.

also, I'm not sure if it is worth the risk that for a future beta-phase the For-Loop wouldn't be stable any longer, and the risk not to manage to solve it until stable version.

is it worth to anger up thousands of customers who were well satisfied with a For-Loop as it is?


I'm just playing the advocatus matris diavoli, nothing more...


so, I want you to ask yourself "is it worth the hussle"?

sure, if Fred would answer to this thread and wrote "yes it is", I would applaude,
but if he answered "no it isn't", I would just shrug and carry on with my own business.
oh... and have a nice day.
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post by Kaeru Gaman »

pdwyer wrote:Give the guy a break Kaeru, he just making a request and it's been noted that others would not like it if it changes the current working with constants (which it might not)

This isn't a Saddam election, you don't have to beat him into retracting his request!

It's a legit request with a legit concern raised. Leave him alone, it's not a court of law
oops, sorry.

I was already writing while you posted this.

yes, you're right.


@akj

I'm sorry, I didn't want to put you down!

I just happen to get carried away with my own arguing sometimes...

peace, mate! Image
oh... and have a nice day.
User avatar
Demivec
Addict
Addict
Posts: 4258
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Post by Demivec »

Kaeru Gaman wrote:
akj wrote:And as it happens the latter emulation code (suggested by KaeruGaman) is flawed as it does not correctly implement the equivalent of

Code: Select all

For x = 5 To 60 Step -9
This is because the body of the emulation loop is evaluated at least once (due to the Repeat statement), but it should not be evaluated at all.
by definition, no!
a For-Loop is defined to be executed at least once.
this is the way it was since I first touched BASIC, over 25 years ago.
@Kaeru Gaman: If a For-Loop is defined to be executed at least once why doesn't it do so with the loop that akj mentioned?

Code: Select all

Debug "loop start"
For x = 5 To 60 Step -9
  Debug "doesn't execute"
Next
Debug "loop over
If what you said is true, PureBasic's For-Loop operates differently, maybe it's a bug. I think that I'll make a bug report that will request the PB manual be updated if this is expected behavior.
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

Post by blueznl »

-1 for the request, I belong to the While / Wend crowd :-)
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
akj
Enthusiast
Enthusiast
Posts: 668
Joined: Mon Jun 09, 2003 10:08 pm
Location: Nottingham

Post by akj »

@Kaeru Gaman:

I gladly accept your peace offer.

This forum is the place to be for friendly, helpful advice and I am happy to go along with that.
Anthony Jordan
User avatar
pdwyer
Addict
Addict
Posts: 2813
Joined: Tue May 08, 2007 1:27 pm
Location: Chiba, Japan

Post by pdwyer »

... and they all lived happily ever after ... :D
Paul Dwyer

“In nature, it’s not the strongest nor the most intelligent who survives. It’s the most adaptable to change” - Charles Darwin
“If you can't explain it to a six-year old you really don't understand it yourself.” - Albert Einstein
Post Reply