In summary, it's up to you.Thanks for your input.
You should use SUB ... END SUB always for1. recursive subs
1. recursive subs
2. variable isolation from main code and other subs
3. passing arguments
Just to add:
GOSUB + RETURN was the original BASIC method for subroutines, such as what you would see in GW-BASIC. SUB + END SUB was a new feature added to QBASIC, and supported by a few other BASIC variants.
I personally recommend using SUB + END SUB, as it can do more, and do it simpler. As far as I know, GOSUB labels do not show up under F2 to list subs/functions, which is a really great feature of SUB + END SUB.
2. variable isolation from main code and other subs
.... This I don't understand. When I pass a variable as an argument, changes made to the variable within the sub changes the original variable. I read that this is by design.
Yes this is true about the variable arguments passed to the sub but all the variables created inside the sub are erased when the sub finishes so if you use an i in the sub, it won't effect the i in the main code as it would with GOSUB.
The only time to use GOSUB in a modern BASIC would be quick-and-dirty proof-of-concept programming.
Just to add:
GOSUB + RETURN was the original BASIC method for subroutines, such as what you would see in GW-BASIC. SUB + END SUB was a new feature added to QBASIC, and supported by a few other BASIC variants.
I personally recommend using SUB + END SUB, as it can do more, and do it simpler. As far as I know, GOSUB labels do not show up under F2 to list subs/functions, which is a really great feature of SUB + END SUB.
...
in my opinion, gosub's are ok, but the problem is that it can lead to some very hard (or impossible) to decipher spaghetti code.
...
Hi Raptor88,
Here is an example of a recursive sub. It calls itself over and over again until the job is done.
IMHO it is the most beautiful and elegant kind of code you can write. I hope this fractal inspires:
.... snip to save bandwidth ....
To further add to what I said:
.... snip to save bandwidth ....
No, we still need gosub today. The concept of a program is to do some big job (I'm waving an arm left to right) and to do that you split it into smaller and smaller jobs. Many you need to do more than once. So write a function or a subroutine.
The first all encompassing gosub anyone will ever need is the "get ready". You call it to set up things for the main process.
Later you might need a "finish up". Close files, tidy things somehow.
If you don't take a large plan and break it into smaller ones you'll never get a program off the ground.
Any program worth looking at will have subroutines. The work is ordered and structured by them. One may make a menu, one loads files, one saves files, one formats data, one gets inputs to add to something, one makes a box on the screen, etc etc etc.
So you mention recursion earlier. I love that. Lots of things can be done with it, but you have to do it right. You'll kill your stack if it gets away from you. Ever see a recursive sort? They are wonderful. I did some recursion, not sure what they were now.
"Spaghetti code is not the fault of GOSUB/RETURN or GOTO, it's simply insufficient knowledge how to do it right."
I can tell you, spaghetti code was almost guaranteed with C=64 or GW-BASIC code. You ran out of line numbers in one part, then used GOTO because renumbering 200 lines of code (and all references to those lines of code) is no fun at all. The more complex the program got, the worse the spaghetti code became. I started mapping out the line numbers in the thousands for the various parts of my programs, just so I never had to renumber anything. It did look silly on small programs, mind you, lol.
The early BASIC spaghetti code was directly the fault of the BASIC editor (or lack thereof). Since Q-BASIC, there has been no excuse for using GOTO or other code kludges. It's been all IDEs since then, probably because of how ubiquitous QBASIC became for new programmers looking to try programming. Even QuickBASIC v4.5 was nowhere near as advanced as say Turbo Pascal (and nowhere near as fast), but for "included with the operating system" it was truly amazing! Light years beyond C=64 or GW-BASIC. I think I've only spent a few hours programming in BASICs that require line numbers since that first time I loaded Q-BASIC.
Personally, I find more modern IDEs to be mostly garbage. QuickBASIC v4.5 was my dream programming environment as a kid, built-in help allowed me to learn [almost] the whole language without opening a book. I find a lot of modern programming IDEs have too much clutter and garbage that gets in the way of actually focusing on programming, and can have performance issues on larger projects. I loved DOS 16-colour text mode GUIs, like PC-Tools and the Norton suite. Very efficient, everything can be done with a couple key clicks. Modern GUIs often require you to use the mouse, or jump through hoops with the keyboard -- why should I have to press 7 keys to do a basic function? I feel mouse-oriented apps often forget about user efficiency altogether -- that is, actually getting the task done in the shortest period of time.
I'm not quite sure what you're asking about F2.
Nobody was suggesting that subroutines are not useful anymore, just that the GOSUB statement is less robust than the SUB + END SUB method.Qwerkey was:
I wouldn't even bother using it then. Just pretend that GOSUB has never existed.
It's like saying who's the greatest super hero, Batman or Superman?
In GW-BASIC (I can't speak for C64 BASIC), you didn't have to hack around with changing line numbers or GOTO/GOSUBing to random code blocks inserted somewhere when you "ran out" of numbers; all you had to do was RENUM your program - you could even renumber sections of your program; see https://www-user.tu-chemnitz.de/~heha/viewchm.php/hs/gwbasic.chm/RENUM.html
Nevetheless reading of old BASIC there was a massive use of GOTO... but I don't know if that BASIC had also GOSUB, SELECT CASE, DO LOOP UNTIL, DO WHILE LOOP, IF THEN ELSE nested...., moreover I read that Pascal rose up to win the massive use of GOTO, but in its keywords there is the same GOTO :-)
Well, if I had known about GW-BASIC "RENUM," I could have saved myself hours of hardship! The books/magazines I read about BASIC did not mention this command. Too bad.
I wonder how many other early BASIC programmers knew about RENUM?
Not intended to be snarky, but ... any of them that really READ the BASIC manual.
C64 BASIC didn’t have RENUM command; it wasn’t added until the last version of C128 BASIC (floppy disk version, I think — maybe some old cartridges).
GW-BASIC had RENUM, but I never saw anyone use it seriously. It was rather silly the way it worked.
RENUM 1000, 900, 20 —- This was a valid command that made no real sense without reading and rereading the documentation over and over....
RENUMber starting with 1000, any number >= 900, and count by 20s...
Everybody got the first and second values screwed up, and RENUM killed code more than it fixed it. Everybody I know, who programmed back in the day, simply used GOTO/GOSUB to scrunch new “blocks” out to insert new code — thus leading to spaghetti code, as we call it now.
Hi Raptor88,
A simple fix to your print SUB, giving it a parameter to pass it an argument to PRINT:Code: QB64: [Select]
PS I don't usually use CALL so I don't have to put arguments inside ()'s
Everything inside a SUB is completely ignorant of variables and values from another part of program. It only knows what you pass it from outside or what is DIM SHARED in main code.
So another way to do this:Code: QB64: [Select]
For solution2, I thought not making all of my variables global using SHARED was the way to go.because with GOSUB all your variables are already in the main and are Global!
Hi Raptor88
I agree with you that each one takes own method to code.
I don't agree with this because with GOSUB all your variables are already in the main and are Global!
So with or without SHARED you use global variables.
A different kind of issue is that rised up by Fellippe
you can make a GOSUB inside a SUB or FUNCTION,
but in this case the variables used in the GOSUB are those Global with SHARED into the main and those local of the SUB where GOSUB is.
If you use DIM SHARED from within a SUB or FUNCTION, it makes those particular variables global only within that SUB or FUNCTION. Using it within the SUB or FUNCTION makes cleaner code, as you know at first glance what is being used globally.
If you use DIM SHARED in your main code, it creates global variables that are accessible in all SUBs and FUNCTIONs.
If you use DIM SHARED from within a SUB or FUNCTION, it makes those particular variables global only within that SUB or FUNCTION. Using it within the SUB or FUNCTION makes cleaner code, as you know at first glance what is being used globally.
Without SHARED, then the variables are not seen within SUBs.