QB64.org Forum

Active Forums => QB64 Discussion => Topic started by: TempodiBasic on September 28, 2019, 06:44:29 am

Title: the Alien WHILE of QB64... a new feature written as old keyword
Post by: TempodiBasic on September 28, 2019, 06:44:29 am
Hi friends

also here you must read before go down with discussion this
the changement to correct the estetic error is not useful like those of interchangeble EXIT FUNCTION  and EXIT SUB  and END FUNCTION  and END SUB

I want remark that
WHILE is not a QB option of EXIT command!
It is a QB64 feature http://qb64.org/wiki/EXIT (http://qb64.org/wiki/EXIT)
... so it would be _WHILE as option of EXIT command

so this code doesn't run in Qbasic
Code: QB64: [Select]
  1.     IF INSTR("WASD", UCASE$(in$)) THEN PRINT in$ + "1": EXIT WHILE
and must be converted in  this using the DO LOOP
Code: QB64: [Select]
  1.  DO WHILE in$ = INKEY$
  2.     IF INSTR("WASD", UCASE$(in$)) THEN PRINT in$ + "1": EXIT DO

It is not an error, but it is an error to pass EXIT WHILE as QB code!

Thanks to read
Title: Re: the Alien WHILE of QB64... a new feature written as old keyword
Post by: SMcNeill on September 28, 2019, 09:37:13 am
I think the reason we have a WHILE and not a _WHILE here is just because of the fact WHILE is already a keyword.

The underscores are to make certain our new keywords don’t conflict with old QB64 code, and in this case, that’s not a concern.  QB64 wouldn’t allow WHILE as a stand-alone variable name, and it won’t allow it after an EXIT statement — so there’s no way we can invalidate existing code with it.

EXIT WHILE might be QB64 specific, but it seems much more natural than an EXIT _WHILE statement (at least to me), especially since we don’t have any sort of _WHILE keyword.  ;)
Title: Re: the Alien WHILE of QB64... a new feature written as old keyword
Post by: Cobalt on September 28, 2019, 11:23:18 am
One other side note, EXITs in general are bad practice. They are a part of spaghetti code. as your not allowing what ever loop is using them to end normally and return as a finished line or section of code.

Not saying they can't be used, just that it might be a better way to think of your code as something that wants to flow smoothly from start to finish with out abrupt turns or changes.

So far I have yet to find an situation where the only choice was an EXIT to do something. At least with QB BASICs.
Title: Re: the Alien WHILE of QB64... a new feature written as old keyword
Post by: bplus on September 28, 2019, 11:41:18 am
One other side note, EXITs in general are bad practice. They are a part of spaghetti code. as your not allowing what ever loop is using them to end normally and return as a finished line or section of code.

Not saying they can't be used, just that it might be a better way to think of your code as something that wants to flow smoothly from start to finish with out abrupt turns or changes.

So far I have yet to find an situation where the only choice was an EXIT to do something. At least with QB BASICs.

Before EXIT there use to be a GOTO someplace outside the loop, that WAS spaghetti!
Title: Re: the Alien WHILE of QB64... a new feature written as old keyword
Post by: Qwerkey on September 28, 2019, 12:41:19 pm
One other side note, EXITs in general are bad practice. They are a part of spaghetti code.

Oh, I thought that EXIT (as opposed to GOTO) to finish a FOR/NEXT, DO/LOOP, WHILE/WEND was terminating the loop properly: effectively it sets the loop to the finish condition(?).  In my most recent program, I did use EXIT for the first time.  I hate bad practice, however.  Is it bad practice?
Title: Re: the Alien WHILE of QB64... a new feature written as old keyword
Post by: FellippeHeitor on September 28, 2019, 01:09:23 pm
Hardly.
Title: Re: the Alien WHILE of QB64... a new feature written as old keyword
Post by: RhoSigma on September 28, 2019, 03:47:38 pm
Hardly.
+1
Title: Re: the Alien WHILE of QB64... a new feature written as old keyword
Post by: SMcNeill on September 28, 2019, 04:12:46 pm
Oh, I thought that EXIT (as opposed to GOTO) to finish a FOR/NEXT, DO/LOOP, WHILE/WEND was terminating the loop properly: effectively it sets the loop to the finish condition(?).  In my most recent program, I did use EXIT for the first time.  I hate bad practice, however.  Is it bad practice?

It doesn’t set it to the finish condition; it just GOTOs the end of it automatically.

WHILE x < 10
    x = x + 1
    PRINT x
    IF x = 5 THEN EXIT WHILE
WEND
PRINT x

The above will print 1, 2, 3, 4, 5, 5 on your screen.  The EXIT WHILE doesn’t make x = 10 (the exit condition).  What it does is basically the same as:


WHILE x < 10
    x = x + 1
    PRINT x
    IF x = 5 THEN GOTO WHILE_EXIT_NUMBER_1
WEND
WHILE_EXIT_NUMBER_1:
PRINT x
Title: Re: the Alien WHILE of QB64... a new feature written as old keyword
Post by: Qwerkey on September 29, 2019, 10:33:37 am
Thanks, Steve.  I see that EXIT is just a brute force GOTO execution.  I see why Cobalt finds this "bad practice".
Title: Re: the Alien WHILE of QB64... a new feature written as old keyword
Post by: bplus on September 29, 2019, 02:06:40 pm
Thanks, Steve.  I see that EXIT is just a brute force GOTO execution.  I see why Cobalt finds this "bad practice".


So what exactly is "bad" about the practice of using EXIT?

It's an extra option to exit a loop, specially a FOR loop which would otherwise have to run through it's entire range or use GOTO or short circuit it's index.

What say Steve? Bad practice or not?
Title: Re: the Alien WHILE of QB64... a new feature written as old keyword
Post by: SMcNeill on September 29, 2019, 02:24:33 pm
So what exactly is "bad" about the practice of using EXIT?

It's an extra option to exit a loop, specially a FOR loop which would otherwise have to run through it's entire range or use GOTO or short circuit it's index.

What say Steve? Bad practice or not?

I don’t think so.  In fact, I think it keeps things much simpler and easier to understand many times, especially with nested events.

DO
    _SOURCE MyImages(Z)
    FOR X = 1 TO Wide
        FOR Y = 1 TO High
            IF POINT(X,Y) = ColorChosen THEN EXIT DO
        NEXT
    NEXT
    Z = Z + 1
LOOP UNTIL Z > UBOUND(MyImages)

Now, with the above, let’s say we have an array of images, and we want to search them in order to find the first one that contains a specific color.  With the above, all we need is the following:

IF Z <= UBOUND(MyImages) THEN
     ‘We found our match.  Z = the image, X/Y = the point where the color was found.
ELSE
    ‘That color wasn’t found.
END IF

Easy to read, follow, and understand.

Now, to do that same thing without the EXIT...

I’ll leave that as an exercise for others, as I’m on my iPad at the moment, but I just can’t think of anyway which you’d code that would be any simpler, or more efficient, than that.
Title: Re: the Alien WHILE of QB64... a new feature written as old keyword
Post by: bplus on September 29, 2019, 02:37:27 pm
Thanks Steve, searching was the first thing that came to my mind as well. I did not even consider loops within loops.
So that is why we have so many loop structures! So we could exit cleanly a multitude of them. ;-)
Title: Re: the Alien WHILE of QB64... a new feature written as old keyword
Post by: TempodiBasic on September 29, 2019, 02:45:06 pm
Premise I use EXIT as soon as I need it

but adding another condition on the cycle  and to the actions that must be done only until the cycle stops

like here:
Code: QB64: [Select]
  1.     _SOURCE MyImages(Z)
  2.     FOR X = 1 TO Wide
  3.         FOR Y = 1 TO High
  4.             IF POINT(X, Y) = ColorChosen THEN Done = true
  5.         NEXT
  6.     NEXT
  7.     IF NOT Done THEN Z = Z + 1
  8. LOOP UNTIL (Z > UBOUND(MyImages)) OR Done
  9.  
  10. IF Z <= UBOUND(MyImages) THEN
  11.     'We found our match.  Z = the image, X/Y = the point where the color was found.
  12.     'That color wasn't found.
  13.  

Quote
It's an extra option to exit a loop
so this option can be put on the LOOP branch with control statements...

but do you think that adding conditions on the cycle can make the code slower than using EXIT ?
I don't know and I need of expert's opinion.

Thanks
Title: Re: the Alien WHILE of QB64... a new feature written as old keyword
Post by: SMcNeill on September 29, 2019, 03:03:17 pm
Your code wouldn’t work.  X/Y continues to change...

DO
    _SOURCE MyImages(Z)
    FOR X = 1 TO Wide
      IF NOT Done THEN
        FOR Y = 1 TO High
          IF NOT Done THEN
            IF POINT(X, Y) = ColorChosen THEN Done = true: XPos = X: YPos = Y
          END IF
        NEXT
      END IF
    NEXT
    IF NOT Done THEN Z = Z + 1
LOOP UNTIL (Z > UBOUND(MyImages)) OR Done
 
You’d need something similar to the above to get the same results (though more inefficiently).

Let’s say we have screens which are 4096x2048 pixels in size (4K HD), and we find the color instantly at point 1,1....

We’re not going to exit that Y loop early, so we do the IF NOT Done check 2047 more times.

We don’t exit the X loop early, so we do it 4095 and the IF NOT Done check there 4095 more times...

And then we FINALLY get to the LOOP UNTIL...Done where we exit... 

That’s over 6000 more repetitions of looking up the value of Done, NOTing it, checking if it’s 0 or not... 

...And, it uses 3 extra variables, which increases our program’s memory requirements/overhead: Done, XPos/YPos (to preserve the X/Y value when we find the match)....

.
.
.

In the end, isn’t it rather obvious which would be less complex to code, and more efficient at the same time?
Title: Re: the Alien WHILE of QB64... a new feature written as old keyword
Post by: TempodiBasic on September 29, 2019, 03:29:12 pm
I agree with you Steve

1. it is more expensive in typing and in use of memory and in debugging (IMHO for my experience)

2.
Quote
our code wouldn’t work.  X/Y continues to change...

I have missed to control the 2 FOR NEXT loop....
here my complete solution....

Code: QB64: [Select]
  1.     _SOURCE MyImages(Z)
  2.     FOR X = 1 TO Wide
  3.         FOR Y = 1 TO High
  4.             IF POINT(X, Y) = ColorChosen THEN
  5.                                Done = true
  6.                                Y =  High
  7.                                X = Wide
  8.             END IF
  9.         NEXT
  10.     NEXT
  11.     IF NOT Done THEN Z = Z + 1
  12. LOOP UNTIL (Z > UBOUND(MyImages)) OR Done
  13.  
  14. IF Z <= UBOUND(MyImages) THEN
  15.     'We found our match.  Z = the image, X/Y = the point where the color was found.
  16.     'That color wasn't found.
  17.  

but it is a BAD practice also to change the counter/index of a FOR...NEXT cycle!   ;-)
Title: Re: the Alien WHILE of QB64... a new feature written as old keyword
Post by: SMcNeill on September 29, 2019, 03:34:26 pm
And you still haven’t preserved your X/Y values like a pure EXIT would.  In your code, you can tell me which screen you found the color on, but what’s the X/Y position where it’s located on that screen?  ;)
Title: Re: the Alien WHILE of QB64... a new feature written as old keyword
Post by: TempodiBasic on September 29, 2019, 05:25:32 pm
Yes Steve
My last code looses informations...
So to correct this my bug I must add 2 lines of code in the IF at the last and a tricky to avoid to use more variables

Code: QB64: [Select]
  1.   DO
  2.     _SOURCE MyImages(Z)
  3.     FOR X = 1 TO Wide
  4.         FOR Y = 1 TO High
  5.             IF POINT(X, Y) = ColorChosen THEN
  6.                                Done = true
  7.                                Y =  Y + High
  8.                                X = X + Wide
  9.             END IF
  10.         NEXT
  11.     NEXT
  12.     IF NOT Done THEN Z = Z + 1
  13. LOOP UNTIL (Z > UBOUND(MyImages)) OR Done
  14.  
  15. IF Z <= UBOUND(MyImages) THEN
  16.     'We found our match.  Z = the image, X/Y = the point where the color was found.
  17. Y = Y -High
  18. X=X -Wide
  19.     'That color wasn't found.
  20.     [ /code]
  21. but it's only a simple example that let to find simple solutions
Title: Re: the Alien WHILE of QB64... a new feature written as old keyword
Post by: SMcNeill on September 29, 2019, 09:07:21 pm
And you just corrupted your program’s data! 

At the start of the program, (which we haven’t shared yet on the forums), was:

DIM X AS _UNSIGNED _BYTE, Y AS _UNSIGNED _BYTE, Wide AS _UNSIGNED _BYTE, High AS _UNSIGNED _BYTE
Wide = 250: High = 250

You just overflowed X/Y!!



LOL!  Don’t pay me any real attention; I’m just messing with you.  (Though you may actually have these sort of issues if the code becomes part of a library which others might $INCLUDE into their code.)

Really, I was just illustrating why an EXIT statement might not be a “bad coding practice”, and might instead be the most elegant solution to a problem.  I think we’ve showed that here, and I thank you for playing along and helping me highlight my point so nicely.

There’s nothing in the world wrong with using an EXIT (or even judiciously using a GOTO in limited situations).  You just don’t want to rely on them so much so that your code spaghettifies and becomes unreadable and impossible to follow the flow and intent of it.  ;D
Title: Re: the Alien WHILE of QB64... a new feature written as old keyword
Post by: Qwerkey on September 30, 2019, 04:30:47 am
Thanks guys.  As both Steve and Fellippe do not think that EXIT is bad practice, on balance we'll go with them (sorry, Cobalt).  When I did use EXIT, it seemed to be an elegant method.  As with all things, just use it with skill (OK, so some of us aren't so hot on the skill level).  I would never use GOTO in any circumstance (no need for Steve to concoct an illustrative piece of code where it would be required!).

Title: Re: the Alien WHILE of QB64... a new feature written as old keyword
Post by: TempodiBasic on September 30, 2019, 07:18:13 am
Great Steve
you have checkmated me!
:-)

At last position it is impossible to save Z, X and Y without EXIT or its workaround by using GOTO Label!

Thanks