"goto cannot be used in strict mode"?

BlitzMax Forums/BlitzMax Programming/"goto cannot be used in strict mode"?

Warren(Posted 2005) [#1]
So the compiler won't check my variable capitalization, but it's more than willing to dictate how I write my programs?

(needless to say, the fact that strict disallows 'goto' isn't mentioned in the documentation)


tonyg(Posted 2005) [#2]
The module ref should have all restrictions.
However, the Language reference under GOTO states...
"GOTO command is supported but only in non-strict mode".
Oddly, Strict doesn't mention this restriction.


Robert(Posted 2005) [#3]
I don't think this is a case of the compiler "[dictating] how [you] write [your] programs", it is probably a technical restriction.

In any case, why do you need to use Goto?


Ole JR(Posted 2005) [#4]
Cut right from the manual, under BASIC Compatibility:

quote:
The Goto command is supported, but only in non-strict mode. Goto labels should be prefixed with a # character.


Why should it be mentioned under 'Strict' that there's no support for Goto if you use it??


tonyg(Posted 2005) [#5]
Because 'strict' in the same Basic Compatbility sections states...
"Strict mode forces you to declare all variables before use."
There is no mention of it preventing the use of Goto.
In addition, this sort of information should be in the Module (command) ref.


Warren(Posted 2005) [#6]
It's under BASIC compatibility? Why isn't it under, say, the "goto" or "strict" command help sections? Since I can't search the help file, those would seem to be the logical place to put that information.

As for why I need to use "goto" ... I'm nested 3 levels deep in 'for' loops and wanted to exit quickly without having to have a bool variable that every loop has to check every iteration. "Goto" has uses, despite the popular dogma.


teamonkey(Posted 2005) [#7]
In for...next loops you should use Exit or Continue instead.


Beaker(Posted 2005) [#8]
I'm surprised we didn't get the much requested:
Exit [n]
command, where n is the number of loops to exit.


Warren(Posted 2005) [#9]
In for...next loops you should use Exit or Continue instead.

Brilliant. Perhaps you missed the part about them being nested 3 levels deep.


teamonkey(Posted 2005) [#10]
Brilliant. Perhaps you missed the part about them being nested 3 levels deep.

Perhaps you could restructure? Or maybe not use Strict mode since you don't like the behaviour. Or you could put your nested code in Functions which return whenever you like. Or you could use a status flag. Or even just use Exit three times.

But then why change your code when you can change the language?


N(Posted 2005) [#11]
Warren: What he means is you should give up ease of use and type out- for every higher loop- code to check and exit.

Personally, I think that's a complete pain in the ass.

So why can't we use Goto with Strict? What logical reason is there?


Warren(Posted 2005) [#12]
teamonkey

Your input is valued and will be filed accordingly.

Noel

That's what I ended up doing. I added a bool variable and every 'for' loop checks it - if it's true, they exit. Lame, but I have little choice if I want to use 'strict'...


Robert(Posted 2005) [#13]
You can use Try...End Try, although you cannot throw Null exceptions at the moment:

Try
	For x=0 To 640
		For y=0 To 480
			If x > 20 Throw ""
		Next	
	Next
Catch result:Object

End Try



fredborg(Posted 2005) [#14]
Another and just as hacky option is this:
Strict

BadLoop

Function BadLoop()
	For Local i:Int = 0 To 100
		For Local j:Int = 0 To 100
			For Local k:Int = 0 To 100
				Print i+","+j+","+k
				If i = 1 And j = 1 And k = 1
					Return 
				EndIf 
			Next
		Next
	Next
End function



fredborg(Posted 2005) [#15]
And the cunning one:
Strict

For Local i:Int = 0 To 100
	For Local j:Int = 0 To 100
		For Local k:Int = 0 To 100
			Print i+","+j+","+k
			If i = 1 And j = 1 And k = 1
				i = 1000000
				j = 1000000
				k = 1000000
			EndIf 
		Next
	Next
Next



ImaginaryHuman(Posted 2005) [#16]
Goto is okay with me. Not so easy to keep track of what's going on but that's not the only point.

I am guessing that Goto is disabled in Strict mode because of something along the lines of the compiler needing to go through the sourcecode in a single forward direction and dip into any function definitions and such as a hierarchy.

Also the very idea of Strict is that things need to be defined before they are used, ie Functions or variables need to be defined higher up in the code before they can be used (which I think actually is a limitation). So that very rule enforces a paradigm of making sure everything is in `order`. .... so you can't really then go using Goto which totally denies any kind of order - the compiler wouldn't be able to deal with that if it needs things to be in sequence. And probably it would be a lot more work to get the compiler working with allowing a strict mode that lets you jump around, which is a contradiction in terms anyway.

That's my take on it.

Personally I'm not using strict mode and I like it. I like that I don't HAVE to put definitions higher up in the code, and I don't therefore HAVE to write such structured programs. It makes things harder to write and forces you to have to make difficult decisions about what is defined where, which is just one more headache for me. I like that I can refer to variables and functions that are further down in the code beyond where they are called. It's natural.
To me, "Strict" is added for backwards compatibility with the old way of doing it, while non-strict is actually an improvement.

And you can never have enough Goto's ;-) Pity there is no Gosub though.


Warren(Posted 2005) [#17]
I like that I don't HAVE to put definitions higher up in the code

Higher up?

Instead of:

x = 0

...use...

local x = 0

Oh noes!!

It makes things harder to write and forces you to have to make difficult decisions about what is defined where, which is just one more headache for me. I like that I can refer to variables and functions that are further down in the code beyond where they are called.

I don't think you understand what strict does. Have you actually tried turning it on?


MrCredo(Posted 2005) [#18]
STRICT

LOCAL dummy
GOTO skipit

LOCAL alien
#skipit
alien=1 <<<<<<<<error, you do not definded this variable

This is a problem for blitzax. C++ compiler can handle this, but not blitzmax.

I think, GOTO must exist always - if you use Strict or not... Coding without goto is a problem for me. With Goto you can very elegant solve some problems.

Sample:

WHILE dummy
#again
FOR i=...
FOR j=...
REPEAT
IF xyz=1 THEN goto again
FOREVER
NEXT
NEXT
WEND

or should i create every time a new function, when i have this code???


Perturbatio(Posted 2005) [#19]
Global Done=False
while not Done
Local gotoStart

gotoStart = False

for j=0 to 10
    for i = 0 to 10
       Repeat
          if xyz = 1 then gotoStart=True
       Until gotoStart
       if gotoStart then exit
    next
    if gotoStart then exit
next
if argbg = 12 then done = true

wend




Warren(Posted 2005) [#20]
Yeah, that's the wonderful bool method. Pretty, huh?


MrCredo(Posted 2005) [#21]
Perturbatio - your code is a joke. who write such unreadable codes? this is not a alternative for goto - this is only a workaround. goto was "designed" for such codes, to eliminate creating tmp-variables. A function is also a workaround. Not existing goto in strict mode is a problem.

http://en.wikipedia.org/wiki/Workaround


Perturbatio(Posted 2005) [#22]
Remind me never again to involve myself in a thread that you are posting in.


Warren(Posted 2005) [#23]
It would help if you read the thread first since this bool work around is mentioned in the 6th post.


N(Posted 2005) [#24]
Perturbatio: They both have very good points. Like it or not, that code is crap for anyone wanting to simply exit several nested loops.

I wanted Beaker's 'Exit[ n]' procedure, but we're obviously not going to get anything akin to that.


AntonyWells(Posted 2005) [#25]
continue can be used to return to top of a loop. use it with exit.


For X=1 to 640

if Line(X)=0 Continue
For Y=1 to 480

  IF Pix(X,Y)=0 Continue 'skips code below
  Pix(X,Y)=Pix(X,Y)*whatever
  If Pix(X,Y)=Done Exit

Next

Next


I've not need goto since using continue..sometimes you have to structure your code slighty differently but it's better than nothing.


AaronK(Posted 2005) [#26]
Well if you're not using Strict you're just asking for trouble. So turn it on and then you can't use goto so don't worry about it.

Blitz should be Strict by default - even more, it should ONLY be strict. Being able to create variables without givien them a type is perilous.

Exit [n] sounds quite nice - that would have been a good thing. Far better than GOTO which sucks.

Aaron


FlameDuck(Posted 2005) [#27]
Brilliant. Perhaps you missed the part about them being nested 3 levels deep.
Then use while.


Warren(Posted 2005) [#28]
Brilliant. I'll file your input next to teamonkey's.


Curtastic(Posted 2005) [#29]
why is everyone arguing about how to not use goto?
In theory Strict should have no effect on Goto. why does it?


Warren(Posted 2005) [#30]
Because 'goto' is a pavlovian trigger. Programmers see it and their fingers take over - they can't stop typing until they've shared their views on its usage, calling you an idiot for using it, and calling your sexual orientation into question.

Anyway, the only reasonable response I've seen is the one from MrCredo ... if the goto skips the declaration of the variable, that might be a problem.

However, it's not a problem for any other language so I wonder why Blitz would take issue...


ImaginaryHuman(Posted 2005) [#31]
Who knows, maybe it was just a design decision to not allow Goto's when in strict mode, to encourage programming style.


Warren(Posted 2005) [#32]
The last thing the compiler should be doing is dictating style to me.


skidracer(Posted 2005) [#33]
Mark did explain it to me once, and I'm pretty sure it was mainly to do with non strict not having scoped locals as in they are all in scope at the top of the function so goto is not so problematic.

Until now I've been using the Return solution, as in if I've needed to exit twice out of an internal loop it has been very simple to move the code into it's own function/method with the code becoming more readable as a result.

I hadn't considered the throw option, and I like it. If an inner loop needs to terminate the operation I can quite happily think of it as an exceptional situation and you get the opportunity to add some extra code to handle it that doesn't bulk up the looop code.


Bot Builder(Posted 2005) [#34]
Skid - what's wrong with Exit [n] then? this'd be awesome.


AaronK(Posted 2005) [#35]
Thinking about Exit, maybe an Exit loopvar would be better in someways. Then you wouldn't have to actually know the # of loops you want to exit from. Problem with that is that it won't work for things like While, Do etc.

Aaron


Bot Builder(Posted 2005) [#36]
Err, yeah. Exit # is better ;)


Russell(Posted 2005) [#37]

As for why I need to use "goto" ... I'm nested 3 levels deep in 'for' loops and wanted to exit quickly without having to have a bool variable that every loop has to check every iteration. "Goto" has uses, despite the popular dogma


Correct me if I'm wrong, but can't jumping out of a stack-based loop without adjusting the stack (popping the last address) come back to bite you in the a** later?

Some languages that have an Exit command, such as PowerBasic, support a syntax of:
Exit [number of levels] ' Default is 1

Sorry AaronK, didn't see your answer. This, I think, should be easy to 'fix', right?

Russell


FlameDuck(Posted 2005) [#38]
Brilliant. I'll file your input next to teamonkey's.
Or maybe since you're not taking my advice, ask someone whose advice you do take to explain to you about "Algorithm design".

In theory Strict should have no effect on Goto.
What theory is that then?

Correct me if I'm wrong, but can't jumping out of a stack-based loop without adjusting the stack (popping the last address) come back to bite you in the a** later?
Ah, beat me to it...

However, it's not a problem for any other language so I wonder why Blitz would take issue...
Maybe this is a bad time to point it out, but it's a problem in Java and C# too...


John Pickford(Posted 2005) [#39]
exit[n] is a horrible solution. Worse than goto which is at least readable. It doesn't even point to a label so you'd have to study the code to figure out where it's going.

I think it *IS* odd to have goto work in non strict mode but not in strict mode. Best to get rid all together.


Difference(Posted 2005) [#40]
Correct me if I'm wrong, but can't jumping out of a stack-based loop without adjusting the stack (popping the last address) come back to bite you in the a** later?

Luckily it's not for us to worry about. If it's allowed in the language it's the problem of the compliler writer. (Mark)

Some languages that have an Exit command, such as PowerBasic, support a syntax of:
Exit [number of levels] ' Default is 1

You must be thinking of some other language. The PowerBasic syntax for exiting multiple loops is:

DO
  DO
    EXIT, EXIT  ' exit both loops
  LOOP
LOOP
As you can see from the declare, PowerBasic does have a lot of cool features to deal with this issue: (from PowerBasic Help)

Purpose: Transfer program execution out of a block structure.

Syntax: EXIT [FOR | FUNCTION | IF | DO | LOOP | MACRO | SELECT | SUB | TRY]

EXIT [, EXIT] [, ...] [, ITERATE]

Remarks: The EXIT statement lets you leave a structure prematurely. Using EXIT by itself will leave the most recently executed structure. For example...


Bot Builder(Posted 2005) [#41]
Correct me if I'm wrong, but can't jumping out of a stack-based loop without adjusting the stack (popping the last address) come back to bite you in the a** later?
hmm. I admit not knowing how to write a compiler, but here's how I would imagine it'd work:

(yes, i know, not asm yada yada, this is just an asmish lang i've made up just now thats pretty low level. not low low though :P)
SET i,0    'Line 1 
CMP i,100,4'Line 2 If i=100 jump to line 5, else continue
ADD i,1,i  'Line 3 i=i+1
JMP 2      'Line 4 Go back to line 2
Why have a stack? This can of course work for the other loops as well, simpler in most other cases.

exit[n] is a horrible solution. Worse than goto which is at least readable. It doesn't even point to a label so you'd have to study the code to figure out where it's going.
Yes, but according to skid/mark you cannot use goto in strict mode, so we look for alternatives. Even if it isnt so readable, if you have your code indented its no problem to find where execution pops back out.


Craig Watson(Posted 2005) [#42]
Excuse me, but:
The last thing the compiler should be doing is dictating style to me.

Is a steaming pile of crap. Next time I'm working with C++ I'll suddenly start typing in some Lisp shall I, and see how it goes. Then I'll whinge to Microsoft because their C++ compiler doesn't support Lisp, right?

The whole challenge of programming is to work within the constraints of the language, which the compiler adheres to. If there was no challenge involved we wouldn't need programmers and there wouldn't really be programming "languages".

Now you can suggest stuff be changed I guess, but I can get by fine without goto and plenty of other people have come up with good enough work arounds.

I'd rather the function of strict wasn't changed or that goto was dropped completely. And John Pickford is right, Exit[n] IS horrible. Mark COULD add another compiler directive to support goto while allowing strict variable name handling.


Craig Watson(Posted 2005) [#43]
The problem with Exit[n] is readability and maintenance. I think multiple exit commands would be easier to see, plus stating what kind of loop you're exiting. It'd be better to max out all your for loop variable values, so it's clearer which loops you are exiting from.


Bot Builder(Posted 2005) [#44]
Is a steaming pile of crap. Next time I'm working with C++ I'll suddenly start typing in some Lisp shall I, and see how it goes. Then I'll whinge to Microsoft because their C++ compiler doesn't support Lisp, right?
Erm, what part of "style" did you not understand? Style is preference in methods to do something, within the reasonable framework of the compiler.it is unreasonable that goto should be restricted in this way, although, according to skid there are some internal complications.

The whole challenge of programming is to work within the constraints of the language, which the compiler adheres to. If there was no challenge involved we wouldn't need programmers and there wouldn't really be programming "languages".
Only for noobs. The challenge and point of programming is to define specificly how to do a task. The challenge is nto working within the constraints, it is rigourously defining how to do something, without error.

And John Pickford is right, Exit[n] IS horrible.
Exit [n] is not.

One option is to set a flag, and check it in each loop you want to exit. not only is this even more cryptic than doing an exit [n], but requires alot mroe processing. Another is throw. I'm not sure how much processing it takes, but concider this with exit [n]:
For a=0 To 100
 For Local b=0 To 100
  If b=10 Then Exit 2
 Next
 For Local c=0 To 100
  If c=10 Then Exit
 Next
Next
Not a practical example, but you get the idea.

The Function one is prolly the best, but there's still the function calling overhead. And then you can't use the local vars, unless you pass them ByRef. Its all ugly. Except Exit [n].

BTW, MrCredo-
Perturbatio - your code is a joke. who write such unreadable codes? this is not a alternative for goto - this is only a workaround. goto was "designed" for such codes, to eliminate creating tmp-variables. A function is also a workaround. Not existing goto in strict mode is a problem.
No, goto is a remnant from previous basics that happens to be useful for exiting loops.

Also, YOUR code is a joke:
WHILE dummy
#again
FOR i=...
FOR j=...
REPEAT
IF xyz=1 THEN goto again
FOREVER
NEXT
NEXT
WEND
Who write such unreadable code? Its not even indented. And all the commands are in caps.

[EDIT]Cross post - craig, thats actually a rather good method. The only problem is that the code after the end of the current loop, inside the loops you are exiting will execute an extra time:
For Local i=0 To 100
	For Local a=0 To 100
		If a=20 Then
			a=1000
			i=1000
			Exit
		EndIf
		Print a
	Next
	Print i
Next


Exit [n] is still better :)


Craig Watson(Posted 2005) [#45]
Sorry if this is a bit rough, it's been a long day..

You're asking for an unsupported language statement. It has nothing to do with style. It's the same as me suddenly writing in French and expecting you guys to understand it. That has nothing to do with style at all.

You're programming in a language, and programming, just like writing, is working within the limitations of that language whilst still being understandable. You might be able to pull off some weird crap in English and still be understood, but nobody is going to like you for it, and the fact you can doesn't mean that you should.

The style you use really has plenty to do with the language. Ask anyone that has used a more rigid language than C or Basic. Dropping the goto statement helps avoid any confusion over where and at what state a loop has terminated. Heavily nested loops are likely to use the stack, because the x86 doesn't have that many registers.

It's a throwback to assembly language of old, and doesn't fit as well with the way compilers are optimised to work now. Goto relates directly to a jump instruction, and a jump instruction, unlike a call, doesn't store and clear the stack. I'm not sure what exact implications would come of this, but if you didn't write your compiler to expect potentially extra stuff pulled or pushed on to the stack, once you try to pull off it, you could have a mess to deal with.

Of the two virtual machines and lexers/compilers I've written, neither of them included a goto like function, simply because of the potential headaches involved. But then I wasn't writing a full on basic compiler anyway.

The problem I have with Exit n is that it doesn't tell you what kind of loop you're exiting, and it's an ongoing maintenance issue, such that

For t = 1 to 20
   if job = nut then exit
   For u = 1 to 40
     if jeep = weep then Exit 1
     if goober = blog then exit 2
     For v = 8 to 400
        If blah = goo then Exit 3
        if meep = shoe then exit 2
     Next
   Next
Next

Add another loop, or fit in another for, and suddenly you have a mess on your hands. And my example has basically no code in it. Stick the usual mess that people put in for loops in there. That's why you'd want to be more explicit about what type of loop you're exiting at least (cos remember we have more than just for loops), and more so setting the variable to the max value will make that much clearer to you or whoever looks at your code later. It also fits quite well with While type loops.

You do raise a fair criticism of that method however, but it depends on the style you use :P The difference with Exit is it would kick you out straight away, whereas if you set the variable you'll still execute whatever is left in that loop before the Next.

You would have to customise your code to suit, and arguably this method is pretty ugly as well, as there could be a long list of variables to set, and again maintenance work to do should something change. Bear in mind though that you'd be dealing with the exact same situation if you elected to use a while/wend loop instead.

Exit is definately preferable to goto-ing out of a loop, which is ugly and hacky as hell in my point of view. If you must have a nested Exit, please somehow make it "Exit [loop type]" at least.

Oh, and the challenge is working within the constraints. You only have x many commands available to use to represent algorithm y. If this was meant to be easy you'd just magically have algorithm y already. Stupid example: If your language doesn't come with a command to input a whole string at once, only single characters, you write a function to stick the single characters together into a whole string. That's what programming is about, working within the language constraints, such as lack of a particular function, to get it to do what you want.

That's what essentially Warren has done, there's no Exit command for nested Fors so he's been using Goto. Unfortunately Goto has become deprecated, so unless it becomes available again, he needs to work around it.


Warren(Posted 2005) [#46]
Guys,

I really don't care what your feelings are on the merits of goto. Please turn off your dogma regurgitators and focus on the issue at hand, which is how to exit from multiple levels of nested loops. The fact that some of you think nested loops are an algorithm design problem shows that some of you need some real world experience - school doesn't represent the reality of coding. You're going to be using nested loops one day, trust me. And on one of those days, you're going to want to exit out of the inner loop and move on with the rest of your code.

"goto" was a good solution for that. "Exit [n]" would work but I'd prefer some sort of label system for that. Being able to stack "exit" statements might work well enough...


Warren(Posted 2005) [#47]
Is a steaming pile of crap. Next time I'm working with C++ I'll suddenly start typing in some Lisp shall I, and see how it goes. Then I'll whinge to Microsoft because their C++ compiler doesn't support Lisp, right?

Yes, because programming style and language syntax are the same thing. Another brilliant contribution.


Difference(Posted 2005) [#48]
Here is another way to exit a nested loops in PowerBasic:

FOR i = 1 TO 10
  DO UNTIL x > 10
    ...
    EXIT FOR  ' will exit DO and FOR NEXT loop
  LOOP
NEXT



Beaker(Posted 2005) [#49]
Peter - Thats funky. Could be good.

Another option would be to allow Exit to reference a label. So that it functions just like a Goto but with more constraints:
For i = 1 To 10
  While x > 10
    '...
    Exit label
  Wend
Next
#label
This would bypass all the complaints about Exit[n] etc.


QuietBloke(Posted 2005) [#50]
wasnt the try / catch a solution to the problem of exiting multiple levels of loops ? or is there something wrong with using this method ?


Warren(Posted 2005) [#51]
You want to write a try/catch scaffold around every nested loop iteration you write? Be my guest.


flying willy(Posted 2005) [#52]
for a=0 to 100
if quit=true exit
for b=0 to 100
if quit=true exit
for c=0 to 100
if quit=true exit
next
if fanny then quit=true
next
next


Craig Watson(Posted 2005) [#53]
Knock yourself out then Warren, you're obviously much smarter than the rest of us with no real world experience.

Your forum whinging is working much better than changing your "style" or adopting one of the many alternatives posted, which actually work with the compiler you're using.

I'll be protesting Mark add a MakeGameForWarren() function next. You leave it to me!

Have you ever actually stopped to think why Goto might have been removed from strict mode? Or why Gotoing out of a loop might not be such a good style?


Bot Builder(Posted 2005) [#54]
mephitis - thats the 3rd time that methods been posted

Exit [loop type] cannot handle many, infact, most cases where you want to exit a hierarchy of loops

Style is limited by the compiler, yes, but is still serperate. The point is that the compiler is for no reason applying certain limitations that should not in our minds be there.

Craig - What's so hacky about using goto? The only headaches i can think of are gotoing out of functions/into, which wont be allowed anyway. AFAIK, there should be no problem using a simple JMP command out of the loop. As long as you arent using a stack, which atm i'm not sure why anyone would use a stack for loops.


Craig Watson(Posted 2005) [#55]
If it's not supported by the language, you can't use that style. How simple is that?

You'll always be using the stack. If you're using nested loops moreso. The x86 Loop instruction for example ONLY uses the cx register (well it used to, dunno if that's changed) as a counter, therefore any nesting you do would have to move from other registers or pull off the stack. There are of course other ways to write loops but I'm sure you'd be using the stack at some point for these also.

The potential is you exit out of the loop with a jump and still have crap on the stack that your program isn't necessarily expecting to be there. Perhaps your jump even skips some pushes so there's not as much on the stack as there should be. Whether this has an impact depends on a lot of factors, but typically I would assume it'd work OK, and sometimes not. You'd probably have to write some extra assembly around all your loops and labels just to ensure the stack is in the expected state at the end.

And then we also have PowerPC assembly to consider which I know nothing about.

And there are good performance reasons to restrict how you exit out of loops. You won't need to stick extra comparison instructions in nested loops you don't need to exit out of. You could actually unroll some loops if you want to. Depends on the compiler again, but it's difficult to write for all cases plus two CPU platforms.


Bot Builder(Posted 2005) [#56]
True, but that's why there is a problem, and why this thread exits ;)

As you know, I dont know much about ASM except a few of the most important commands. Never was much of a reason to learn it. You can have JMP "goto" a specific point in the program. Use this for the ends of the loop. Then just do comparisons, increment a variable using whatever system bmax uses, and then do all of the asm after words, repeat. where is there stack use in this?


Craig Watson(Posted 2005) [#57]
Because you only have four general purpose registers? Registers=super fast, memory=super slow (a read from non-cached memory can take several cycles, which your code will have to wait on.) You want to use registers as often as possible, preferably in any one code block read directly from a memory location once and write once. And stack based processors would generally be optimised for using the stack as opposed to doing memory transactions all the time. So, you push and pop constantly.

I wouldn't pretend to be all knowing about x86 assembler, but there's typically much more going on than there should be because it's all based on 1980s technology. This is pretty much what I know of it, so some might have changed a fair bit now we're using pseudo-x86 modern processors on multi-tasking environments.

To write really quick code you need to have a very clever compiler that manages the registers and the stack well. You also need to consider that the code you generate will typically be very generic. You may end up writing a function that uses the stack even though it doesn't always have to, simply because it MIGHT have to. It's far more complicated than just writing the basic code straight into its assembly equivalents. Then you have to consider what asm the processor itself will optimise. A missed branch prediction on a PIV CPU will have to empty the whole pipeline, which I guess means you'd want to limit the amount of branching you do.

I could probably mock up some pseudo assembly to show you what I mean, but google x86 asm and you'll probably find some perfect examples of ugliness. Having a basic understanding of asm can help you write better higher-level code too.


marksibly(Posted 2005) [#58]
Hi,

(Ok, this will be confusing).

The main reason Goto is not supported in Strict mode is that it can cause highly irregular code paths that can confuse the compiler and prevent a bunch of optimizations.

For example:

Goto there
Local tmp=100
#There
Print tmp

...means that 'tmp' must be initialized prior to the Goto or you'll get a nonsense result. Which means that locals can not necessarily be initialized where they appear in the code. Which, combined with the fact that Goto can jump in and out of scopes, complicates the compiler immensely.

The solution for non-Strict mode is simply to move all Locals up to the 'top scope'. But this can severly limit optimization, eg:

If x<y
Local t=10
...blah...
Else
Local q=20
...blah...
EndIf

In non-strict mode, both t and q are 'moved up' to the top level, and the code to 'null them out' is always executed - even though only one of them is ever used.

However, in strict mode, the locals are only initialized if their codepath is taken - eg: if x<y, then q is never initialized and vice versa.

Yes, it is possible for code analysis to deal with these issues (or at least, detect them), but it's complex and I didn't think worth the time. C++ does this, but it can generate some bizarre related error messages, like 'initialization of blah skipped by whatever'.

And yes, Strict mode code should be slightly more efficient!

I haven't used Goto for many, many years now and have got by fine. Although thinking about it now, I suspect I tend to 'functionize' blocks if they get too deep and I need an early out.

I don't like either 'Exit 2', 'Exit For', 'Exit For, While' or whatever. All these solutions mean that changing or adding enclosing blocks is potentially dangerous.

Instead, I would tend to go with Java's solution, which allows you to 'label' a block and then use Exit with that label, eg:

#MainLoop 'In strict mode, must be followed by an 'exitable' statement
While blah
Exit MainLoop
Wend

This is definitely doable.


Bot Builder(Posted 2005) [#59]
Huh. Interesting. Yeah, I remember registers from the slight bit of ASM I ever did. Obviously you use them because otherwise you cant do anything. Didn't know stacks were so much faster. That explains it then.

[edit]I've found a good tut... might learn asm ;) Course, i was thinking the same thing when i tried doing stuff with it ages ago.


Beaker(Posted 2005) [#60]
I like Marks solution. Its actually visibly better than my 'near' solution, cos you can see the definition of the block at the top instead of the exit point at the bottom.

"Functionalizing blocks" seems like an anti-"good programming" solution. Waters down the power of functions in readability terms.


Difference(Posted 2005) [#61]
#MainLoop 'In strict mode, must be followed by an 'exitable' statement
While blah
Exit MainLoop
Wend

This is definitely doable.

Sounds cool to me.


Craig Watson(Posted 2005) [#62]
Thanks for confirming some of that Mark. And it's possibly good news for those who want an Exit to label function too.

I haven't worked directly with x86 assembler for at least six years now (and back then it was pre-protected mode stuff), so it's good to have a bit of confirmation for what I've assumed was still the case.

Stacks are obviously not faster than registers, but I'm guessing that any stack based processor is going to try to keep them closely cached so they'll be a lot faster than memory reads.


Curtastic(Posted 2005) [#63]
thanks mark, I totally agree


marksibly(Posted 2005) [#64]

"Functionalizing blocks" seems like an anti-"good programming" solution. Waters down the power of functions in readability terms.



Depends on the context. There are definitely some situations where a block becomes complex enough to deserve its own function - if not for efficiency sake than just for plain readability. Also, functionalizing a block can sometimes allow you to clean it up significantly - ie: removing the glue/flags that allow it to execute within another block.

On the other hand, if I had 'Exit label' I'd probably start using it!


Stacks are obviously not faster than registers, but I'm guessing that any stack based processor is going to try to keep them closely cached so they'll be a lot faster than memory reads.



None of the above is really anything to do (directly) with the CPU. Even with infinite registers, the 'Goto' example above would still require the extra code to null out both t and q (in case there was Goto somewhere) that the Strict version can omit.

A realated issue is local 'liveness' - consider...

Local t=100
'...code...
'...code...
'...code...
Print t

In this code, 't' is live for a long 'time'. This means you get more intereference between t and any other locals between its definition and its use. Too many interfering locals and you start spilling - ie: having to store some of them in memory as there aren't enough CPU regs.

Non strict mode can artificially extend the live range of locals, which can lead to more spills and slower code.


Craig Watson(Posted 2005) [#65]
Sorry Mark, my post wasn't in reference to that, it was because of what Bot Builder said about stacks. I didn't want to imply they are just as good as registers. Obviously if you could, you'd use registers for everything.

I think given what you've said though we actually pretty much agree on everything. It also confirms what I thought about strict producing more optimised code.


Bot Builder(Posted 2005) [#66]
Yeah, i gathered that. You have registers to point at stacks, so you automatically know that they arent as fast ;)

Anyway, Now I know what buffer overflows are!!! sweet :) So that would be why you can execute foreign code using it.. Bad design, imho.

Anyway, that post right after marks was when i hadn't seen mark's. and i've just seen it now. And yes, that method looks great :)

strict is more efficient, eh? Sweet.

Oh, and, mark, what's the word on overidden functions/ private members/ properties? I'd like a definite yex/no so i can stop mentioning it in any relevant thread ;()

private members especially, as there are some things you dont wnat messed with. For instance, it seems that in the modules the fields starting with "_" are things you would normally have private. Is this functional or is it just to make it harder to guess or something? However, overridden functions would be very handy because you can't use the determine type trick on builin-types, to make a function that responds to totally different data types. Having functions with different numbers of parameters isnt as useful, and more confusing, Properties are useful because they replace the theory of making a bunch of set/get functions for all your fields (so later on you can make additional code execute when something is set/gotten, or you can apply some procesing, whatever). Using the old system people would often create massive lists of set/get functions so later on you could add code while keeping back-compatability. Properties changes that. You access fields like they should be. As variables. When you want to make a property for a field, you make the actual field private, change its name a bit, create a property with get/set methods inside. Then, you maintain back compatability and field-syntax.


Warren(Posted 2005) [#67]
Mark

The "Exit #label" solution sounds perfect to me!

And thanks for the info about strict and how it initializes variables. Interesting, and very useful info...


MrCredo(Posted 2005) [#68]
If Exit #label is doable, please add it as a alternative to gito. I think the most time we need goto to jump out from a for/while/... loop


Bot Builder(Posted 2005) [#69]
wierd. I always need it for jumping out of a giant hierarchy of for loops....

in my current project, in the same function, I have While/for/if/for as well as for/for/if/for.


Jeroen(Posted 2005) [#70]
The last thing the compiler should be doing is dictating style to me.


Well, the compiler is already doing that without 'Strict'. You need to program "Blitz Style", and if you turn on, it's "Blitz bithin' style".


flying willy(Posted 2005) [#71]
just... DUMP goto while you're at it too. Just dump stuff that doesn't work in strict.

Get rid of it.


Bot Builder(Posted 2005) [#72]
Yeah, whenever i create a new program i just punch out strict/framework/imports.


Warren(Posted 2005) [#73]
Well, the compiler is already doing that without 'Strict'.

No, with strict it's dictating syntax, not style.


FlameDuck(Posted 2005) [#74]
"Functionalizing blocks" seems like an anti-"good programming" solution. Waters down the power of functions in readability terms.
Actually it's called Refactoring (or rather method extraction) and is generally considered very good programming as it makes code more readable and easier to read and understand.


Beaker(Posted 2005) [#75]
You cannot argue that refactoring is a good solution to exit-ing multiple loops. That's just plain nonsense.


Dreamora(Posted 2005) [#76]
the question I would like to put in this discussion: beside basic no language has goto ... so how do they work in this situation?
java, c, eiffel etc?


jhague(Posted 2005) [#77]
You cannot argue that refactoring is a good solution to exit-ing multiple loops. That's just plain nonsense.

If the loops are small, such as scanning a two or three dimensional array for a certain value, then exiting multiple loops is clean, simple, and obvious.

the question I would like to put in this discussion: beside basic no language has goto ... so how do they work in this situation? java, c, eiffel etc?
C has goto.


Warren(Posted 2005) [#78]
Dreamora

C/C++ has goto.


dynaman(Posted 2005) [#79]
The most common has been the equivalent of break statements. If you make a function out of the whole thing then some allow a return from within the whole mess.


Sometimes I use a while wend with a "loopcontinue" variable getting set to false. (crude, but it works)


Beaker(Posted 2005) [#80]
junkster - I think you misunderstand the argument.


Beaker(Posted 2005) [#81]
Many languages have "goto". Even Pascal.


ImaginaryHuman(Posted 2005) [#82]
I find Goto to be highly efficient. It is direct and immediate. It doesn't have to involve any conditional tests or pass any parameters. It is the simplest and most efficient redirection of program flow. I think most of the arguments against it are how it affects programming in `the bigger picture` or what impact it has on style or how difficult it is to keep track of, etc. I'm not actually using Goto's right now because BlitzMax doesn't have very flexible labels (label pointers anyone?) But if I had to devise ways of programming without it and I needed it, I wouldn't be too happy about it. I found Pascal programming to be more difficult than it needed to be because (the implementation I used) didn't have any Goto's. Also BASIC programmers got along just fine for years before we had these other language paradigms.


Warren(Posted 2005) [#83]
Also BASIC programmers got along just fine for years before we had these other language paradigms.

That's a weak argument though. Horse and buggy transportation was great too, but no reason not to look at those new horseless carriages as long as we're in town...


flying willy(Posted 2005) [#84]
edited out of respect for others.


Tom(Posted 2005) [#85]
Grow up and show some manners.


Warren(Posted 2005) [#86]
Hint: Changing your username doesn't erase your previous posts.


SJB(Posted 2005) [#87]
As pointed out way up near the top of this long thread, use exceptions. This is the typical, modern way of handling the problem expressed by WarrenM. It is a common mistake to regard exceptions only as error trapping mechanisms. An exception is just an event that happens that will interrupt the normal flow of execution - just like a break/exit does.

If you are worried about the extra overhead of exception handling, then I think your concern is misplaced.


VIP3R(Posted 2005) [#88]
[edit] Thanks for editing skunk


Michael Reitzenstein(Posted 2005) [#89]
well then, get it working in strict or you'll look like a complete tit, mark

I'd like Strict to stay faster, thank you very much.


flying willy(Posted 2005) [#90]
That makes absolutely no sense. If you want to keep it faster, simply do not use GOTO. Remember the globals situation? globals are slower in strict.

Don't make an inconsistent language, mark.


flying willy(Posted 2005) [#91]
edited and taken private to email


John Pickford(Posted 2005) [#92]
tits, you are bang out of order. What do you want? Another locked/deleted thread? An interesting discussion ruined?


Craig Watson(Posted 2005) [#93]
Goto-ing out of a nested loop is not that unusual a practice, and is even suggested in the MSDN. It's just I find it ugly to read and technically hard to cater for compiler wise.

The fact that C/C++/Pascal etc. support it isn't quite true though, because granted while they do support it, it is typically with some limitations that serve to de-fang it. Basic languages of old got along fine with it because not only were most interpreted, but they were rarely strictly scoped (arguably partly why Basic was often slower compiled.)

Providing an alternative for probably the most common modern use of goto is sufficient, and "functionalizing blocks" would allow this while also making it easy to maintain variable scope for the compiler.

So I think to remain strict, either we can have the functionalizing blocks, or a very strict, forward only goto, which is essentially the same thing.


flying willy(Posted 2005) [#94]
Sorry John, you are correct.


FlameDuck(Posted 2005) [#95]
You cannot argue that refactoring is a good solution to exit-ing multiple loops.
But method extraction, and then returning is. Refactoring is a good solution to keeping your code maintainable.

I find Goto to be highly efficient. It is direct and immediate. It doesn't have to involve any conditional tests or pass any parameters. It is the simplest and most efficient redirection of program flow.
Well it was, before the time of smarter optimizing compilers, and simpler CPU constructs. Back when compilers simply translated statements to a lower level language, goto worked as indicated.

I think most of the arguments against it are how it affects programming in `the bigger picture` or what impact it has on style or how difficult it is to keep track of, etc.
Actually most of the arguements against it are the same as against self-modifying code.


Warren(Posted 2005) [#96]
Well it was, before the time of smarter optimizing compilers, and simpler CPU constructs. Back when compilers simply translated statements to a lower level language, goto worked as indicated.

But it works just fine in C/C++ and a dozen other languages that require forward variable declaration - like strict does.

Actually most of the arguements against it are the same as against self-modifying code.

A goto statement that jumps to the bottom of a set of nested loops is hardly unreadable - which is generally the argument against self modifying code, unless you have something else in mind.