This is gonna be long. Can't think of any short way to word this. Can't even get my words right but if I trip over my tongue, you guys no by now that I don't mean anything in a bad way.
@Phaelax:
Quote: "Quote: " Labels don't accept parameters nor return values."
That's not why people use GOSUB, we have functions for that. But not every check of code needs parameters or to return a value."
True, but why bother differentiating? If a function can be used as a sub and a function and a sub only works as a sub then, again my personal preference, just unify the whole thing. Admittedly I'm biased since for a long time, I've perceived subs kinda obsolete (I'm not alone, subs aren't supported in many languages).
Quote: "Quote: "Lack of scope change can wreak havoc with variables with the same name."
Hence why people should use variables with meaningful names."
Yes, I do use logical names. I have my own system for variables and try to use same-names for same-tasks as it makes tracking easier. So if I'm just storing something temporarily, it could conflict unless I had structured my program to be conflict-proof (which I obviousy do nowadays). But for people new to coding, it's not always easy to get that structuring right, hence my suggestion to simply avoid.
Quote: "Quote: "Code debugging can be harder merely due to formatting of labels vs formatting of functions."
Debugging I find is much easier. Code is broken down into various segments, keeping it cleaner and more organized.
"
I guess that's personal taste
I find this:
Main:
// Preamble, intro, init, etc
SetupPlayer()
WHILE StillWantsToPlay = 1
MakeMaze()
// Other stuff
PlayGame()
// Query: Next level, quit, event?
ENDWHILE
// Quit? IF NO, GOTO Main. This avoids an extra nest. Essentially why I say GOTO can be used correctly.
END
Function PlayGame()
WHILE playing
// Do stuff
HandlerFunction
ENDWHILE
// More stuff
EndFunction
Function MakeMaze()
// Blah, blah
// Some queries on difficulty
// Oh look, a cat
// Build a random dungeon
// Plant entities
EndFunction
Function SetupPlayer()
// Build a unique model of the player using
// 4 grey-scale photos from different sides
// and height-map techniques...oops, wrong year.
// Forget what I said. Randomly pick appearance
// attributes.
// Give player a class & skills
EndFunction
Function HandlerFunction()
// Something to handle something. What, I know
// not, but deffinitely something.
// Homonculi. Yes this handles homonculi.
// It makes them with alchemy.
EndFunction
easier to look at than this (I suppose code-highlighting plays a small role too):
Main:
// Preamble, intro, init, etc
GOSUB SetupPlayer
WHILE StillWantsToPlay = 1
GOSUB MakeMaze
// Other stuff
GOSUB PlayGame
// Query: Next level, quit, event?
ENDWHILE
// Quit? IF NO, GOTO Main.
END
PlayGame:
WHILE playing
// Do stuff
HandlerFunction
ENDWHILE
// More stuff
RETURN
MakeMaze:
// Blah, blah
// Some queries on difficulty
// Oh look, a cat
// Build a random dungeon
// Plant entities
RETURN
SetupPlayer:
// Build a unique model of the player using
// 4 grey-scale photos from different sides
// and height-map techniques...oops, wrong year.
// Forget what I said. Randomly pick appearance
// attributes.
// Give player a class & skills
RETURN
HandlerFunction:
// Something to handle something. What, I know
// not, but deffinitely something.
// Homonculi. Yes this handles homonculi.
// It makes them with alchemy.
RETURN
for purely cosmetic reasons. So yeah, my personal taste again (I did say in the previous post that some reasons were subjective). So far as newcomers go, it is unlikely that their subs will be that tidy, nor their GOSUB calls well placed (as was the case with OP's code - no offence OP).
Quote: "Quote: " The fact that in many cases, too many GOSUBs without RETURNs can cause a stack overflow"
That's why we put RETURN at the end of each GOSUB label, and not use GOTO."
GOTO cannot, alone, cause a Stack overflow. GOTO is an unconditional jump without return.
SET WINDOW ON
foo:
GOTO bar
bar:
GOTO foo
AFAIK, that may loop indefinitely but it won't crash because there's no return address.
The following would cause an overflow if DBP didn't have special handling for it that terminated the application:
SET WINDOW ON
foo:
GOSUB bar
RETURN
bar:
GOSUB foo
RETURN
Quote: "
Quote: "Lack of scope change doesn't delete temporary local variables."
You'd prefer to constantly create and destroy a variable over and over from inside a function?"
Yes, within reason. I suppose it would ultimately depend on just how often that call will be made. If I'm going to be using a variable a lot, I tend to declare it with global scope and I usually reduce procedures to require the least amount of temp variables in functions that are called regularly. Essentially though, if I don't need the memory, I don't want it hanging around, eg:
With a Function:
SetupDisplay() // Past this point, I don't need the variables here
// Game or whatever goes here, no need to setup the display again.
WAIT KEY
END
Function SetupDisplay()
// You'll need a non-16:9 display to test this. You can set your monitor to 4:3 if it supports maintaining AR
// ie not stretching.
SET DISPLAY MODE DESKTOP WIDTH(), DESKTOP HEIGHT(), 32
tempSizeX# = SCREEN WIDTH() / 1.0 // I store these to prevent making calls to the SCREEN [HEIGHT() | WIDTH()]
tempSizeY# = SCREEN HEIGHT() / 1.0 // function each tim I want to retrive the numbers.
tempAR# = tempSizeX# / tempSizeY# // This variable is only ever going to be used by this segment of code
IF tempAR# < 1.777
SET WINDOW ON
SET WINDOW LAYOUT 0,0,0
MAXIMIZE WINDOW
tempHeight = FLOOR(tempSizeX# * 0.5625) // I suppose I could combine these all into three sums and shove
tempY1 = (tempSizeY# - tempHeight) / 2 // them at the SET CAMERA VIEW part... but that'd cost more CPU
tempY2 = (tempY1 + tempHeight) // time and also make the code less manageable.
BACKDROP ON
COLOR BACKDROP 0x111111
SET CAMERA VIEW 0, tempY1, tempSizeX#, tempY2 // This is as far as these variable's usefulness goes. They MUST
SET CAMERA ASPECT 1.7 // be killed now and I no longer need them.
MAKE OBJECT SPHERE 1, 5
ENDIF
EndFunction
Using a label and GOSUB instead:
GOSUB SetupDisplay // Past this point, I don't need the variables here
// and yet they linger...`
// insert program here
WAIT KEY
END
SetupDisplay:
// So essentially, this isn't too different from a function call except it'll leave variables behind when called
// from the main module.
SET DISPLAY MODE DESKTOP WIDTH(), DESKTOP HEIGHT(), 32
tempSizeX# = SCREEN WIDTH() / 1.0 // I store these to prevent making calls to the SCREEN [HEIGHT() | WIDTH()]
tempSizeY# = SCREEN HEIGHT() / 1.0 // function each tim I want to retrive the numbers.
tempAR# = tempSizeX# / tempSizeY# // This variable is only ever going to be used by this segment of code
IF tempAR < 1.777
SET WINDOW ON
SET WINDOW LAYOUT 0,0,0
MAXIMIZE WINDOW
tempHeight = FLOOR(tempSizeX# * 0.5625) // I suppose I could combine these all into three sums and shove
tempY1 = (tempSizeY# - tempHeight) / 2 // them at the SET CAMERA VIEW part... but that'd cost more CPU
tempY2 = (tempY1 + tempHeight) // time and also make the code less manageable.
BACKDROP ON
COLOR BACKDROP 0x111111
SET CAMERA VIEW 0, tempY1, tempSizeX#, tempY2 // This is as far as these variable's usefulness goes. They MUST
SET CAMERA ASPECT 1.7 // be killed now and I no longer need them.
MAKE OBJECT SPHERE 1, 5
ENDIF
RETURN
Quote: "To be honest, all these problems are simply caused by incompetent coding and nothing to do with GOSUB itself. (I'm not trying to call you incompetent)..."
No innuendos read into it, promise. And I agree with you whole-heartedly about the problem not lying with GOSUB. As I mentioned before, "GOSUB is not without merit". The same thing could be said about almost any statement, including GOTO. GOTO is a great optimizer but I will tell most people to stay away from GOTO because it requires a very specific understanding of program flow. Because of the myriad of potential problems I mentioned, I also generally advise against GOSUB.
I'm not saying for a minute that everyone should stop using it completely, just that it's one of the things I advise newcomers against if they seem like they're using it wrong. I'd never have the arrogance to say what coding style is right or wrong, I merely suggest what I feel is most appropriate for the individual at the time (based on the code they post along with any extra info I pick up from their post(s)).
Finally, thanks for giving me some things to think about. There's much validity in what you say and I'm prolly one of the few people who would actually be against GOSUB in BASIC (most people are against GOTO instead, it seems).
@TheComet:
Quote: "
function ControlMorons()
rem control all things moron related
gosub _Handle_Brain
gosub _Handle_Stupid_Decisions
endfunction
"
You make GOSUB call INSIDE functions!?! Surely you jest, my good sir!!! ... Actually, it's an interesting usage of GOSUB and, tbh, I'm somewhat intrigued out of pure academic curiosity because that shouldn't even compile (And bumblebees shouldn't be able to fly too, lol) so you've given me a proverbial rubix cube to play with now (more distractions *grumble, grumble*).
Here's the thing though:
x = 100
var = Foo()
PRINT "Returned from Foo : "; var
WAIT KEY
END
Function Foo()
x = 5
PRINT "x start (in Foo) : "; x
GOSUB Bar
EndFunction x
Bar:
x = x + 5
PRINT "x next (in Bar) : "; x
WAIT KEY
RETURN
Putting aside the fact that it compiles and runs, I notice the scope of Bar remains in the scope of the main module. So when I call GOSUB from a function, it's not in the function's scope anymore, but the main module's. So that means you can't alter any of Foo's locals in Bar, however Bar can modify the main module's. That is just a touch dangerous if you're not really careful (I'm sure you are careful if your GC posts regarding that electrical engineering stuff you're into are anything to go by).
Well, even though your method's not compatible with me, I do see where you're coming from regarding the organisation and visual neatness so once again, I spose it does boil down to preference. I guess, as IanM once said, "Pragmatism over dogmatism". If it works and it's comfortable, I suppose it's all good.
Well I'm glad I learned something interesting about DBP from that, so thanks. It seems like just when I think I have this thing waxed, something that shouldn't work turns out to work just fine.
If nothing else, I'm left more open-minded now.