Declare as local, really needed?

BlitzMax Forums/BlitzMax Programming/Declare as local, really needed?

Trader3564(Posted 2008) [#1]
The title says it, i had a quick question on wheter it is or is not good to declare local variables.
I did some tests, and the game runs as well with as without declarations.

Globals, obviously do have function.


Dreamora(Posted 2008) [#2]
Well, you have no option to not declare them.
Code without strict / superstrict will suffer missing optimations etc. As well, your code will not be accepted as "clean" or really acceptable if you ever post it here ... as some of the issues come due to the fact that strict is not used. (its not there for fun. its mainly optional instead of enforced to have the converted Blitz3D / BlitzPlus code working as you can not use strict on those as they use int handles which are a big no no in BM performance wise)

As well, local is very important to the GarbageCollector as the place where you define it defines where it becomes invalid and can be cleaned for sure.
Variable scopes don't exist without strict, beside "function" and "application"


CS_TBL(Posted 2008) [#3]
It's good practice to have as many variables local as possible. That will give better code-reusability, and it's essential for blackboxing. In the true coders Utopia, there are barely any globals.. ^_^


Trader3564(Posted 2008) [#4]
Oh, thanks for the info! In that case ill strict my RPG now i still can :)
When a variable is declared as local, do you recommend i also defint the TType? :Int, :String, :TBank, etc... ?
And if i want to set a default value, how do i add this? for a TBank for example. Would that be =null or, could i just leave it like that? How would this effect the code?


CS_TBL(Posted 2008) [#5]
I recommend Superstrict, that'll teach ya, muhuhaha!


Dreamora(Posted 2008) [#6]
BM default inits stuff. String = "", numerics = 0, types other than strings are = null

And yes, set the type always ... and avoid the "numerics shortcuts" (ie %, # etc as well as $ for string) they are nice for lazyness ... but don't make the code that much better to read.


Trader3564(Posted 2008) [#7]
haha, ok. i already felt the pain of Strict. When im done ill try Superstrict.

In line of all this, i had another question. How important is it to open ( close ) paramaters when calling functions?


I learned that you MUST use () if you want it to return. Otherwise you can leave it as well away. Any comments?


Dreamora(Posted 2008) [#8]
Depends on your own style. I use them everywhere, just to make it visually clear that it is a function, not some kind of strange variable or the like.


Trader3564(Posted 2008) [#9]
My goodness. I just finished the Strict. I GAINED +10FPS.... amazing! just amazing...
I thoughd that the more code i added, the slower it would go. But by defining it all, it even gets waayyy faster.


Dreamora(Posted 2008) [#10]
yupp because the GarbageCollector can flag them as dead and remove them far earlier ... for example a local defined within an IF will be cleaned when you reach else or endif of that IF


Trader3564(Posted 2008) [#11]
cool.

@CS_TBL
hah. i now work with superstrict. its the best :P
i kinda felt it was a bit messy to leave all intgers undefined, so i though, heck, why not? :P


ImaginaryHuman(Posted 2008) [#12]
Local variables tell the compiler to try to use a CPU register to store a value rather than store it in memory. This makes a lot of sense if you are going to be accessing the same values many times or want to work with a relatively small number of variables often. If you are doing lots of bigger memory access or parts of your code are quite different and not re-used much then you might not see any benefit. I try to use as many locals as possible and I never think about the garbage collector (that's the point of it). If I a coding tighter loops or doing lots of calculations I particularly try to put values into locals and generally the code does run faster. I would definitely avoid making all your variables global.


Azathoth(Posted 2008) [#13]
Locals still get stored in the memory, that being the stack.


Czar Flavius(Posted 2008) [#14]
Strict and superstrict are the same apart from strict assumes any variables you have not specified the type of are int. Superstrict requires you to specifiy the type of all variables, even if they are int. The performance between the two is the same - the difference is only cosmetic. (If all but one type of variable are specified, the compiler can safely assume what an unspecified variable is).

Not using strict the compiler can only guess what variable type you are using and because you do not need to declare the variables, it doesn't know where they belong. For example, a variable declared inside an if block using strict does not exist after the endif (try it, on strict) and allows the compiler to make all kinds of wonderful optimizations. For example registers are stored in super-quick memory inside the processor cache, but if the compiler doesn't know where each variable "belongs" it cannot smartly decide which belong in the registers.


Winni(Posted 2008) [#15]
Superstrict should be the one and only default. You know, just as in Pascal. ;-)


Brucey(Posted 2008) [#16]
Superstrict should be the one and only default.

Yep! :-)


Trader3564(Posted 2008) [#17]
ohboy. so even storing local's inside a for/next loop is faster then outside?


Czar Flavius(Posted 2008) [#18]
From a theoretical design point of view, you should make your variables accessable only where they are needed. If they are needed only in a particular section of code, then only that section of code should be allowed to access them.

It just so happens this also tends to result in better and more bug-resistant code. If code that doesn't need the variable, can't get at the variable, then there's no chance it might screw up with the variable.

I'm not too savy on any figures about whether it is faster or not, but from a design point of view, if the variables are only required *inside* the for loop, then declare it only inside the loop. The problem with that, though, is it will reset the variable each time the loop is ran, in which case you have no choice but to declare the variable just before the loop.

In this example we go through some bank accounts and find out how much money they have in another currency if the exchange rate is "rate". You could just store the calculation directly into totalmoney but for point of simple example, let's not.

Local totalmoney:Int = 0
For Local tempaccount:TAccount = EachIn accountlist
   Local convertedmoney:Int = tempaccount.money * rate
   totalmoney :+ convertedmoney
Next



The convertedmoney variable does not exist outside the loop and attempting to access it will make the compiler complain the variable doesn't exist (on strict mode at least!) Which is good, because it doesn't make sense for the convertedmoney variable to continue existing after the loop. Its job is done. Thus potential errors are removed, and possibly the loop will run faster.


Trader3564(Posted 2008) [#19]
...if the variables are only required *inside* the for loop, then declare it only inside the loop. The problem with that, though, is it will reset the variable each time the loop is ran.
try this, works fine:
For Local x:Int = 0 To 10
	Print x
Next



JazzieB(Posted 2008) [#20]
That's not what he meant! In your example, x is defined once when the loop is initiated. What he meant, was something like this...

SuperStrict

For Local x:Int=0 Until 10
	Local y:Int
	y:+1
	Print x+" "+y
Next

In this example y will always return 1 because it's reset to 0 before it gets 1 added to it with every iteration of the loop.


Trader3564(Posted 2008) [#21]
true.


Damien Sturdy(Posted 2008) [#22]
I find declaring Local variables in FOR loops a massive slowdown. this might be due to CPU cache size or whatever technical reason, but if you are after speed, find a way to put the foor loop in a new scope and declare the vars it will use before entering. It may not be great but it is considerably faster.


Dreamora(Posted 2008) [#23]
Yupp definitely ... the constant "reiniting" if local within loop is a considerable overkill.


Trader3564(Posted 2008) [#24]
Thanks for mentioning!!


Czar Flavius(Posted 2008) [#25]
You can 'isolate' a piece of code in a scope like this,
Repeat
 Local heheoutside
 For ...
 Next
Until True


Not very elegant, but it should do it.


Dreamora(Posted 2008) [#26]
enclosing with if true is simpler :)
does the same as using { } without any keyword in C++


WendellM(Posted 2008) [#27]
In this example y will always return 1 because it's reset to 0 before it gets 1 added to it with every iteration of the loop.

Wouldn't using Global (which isn't really a Global in this case, but rather a static local) solve that:

SuperStrict

For Local x:Int=0 Until 10
	Global y:Int
	y:+1
	Print x+" "+y
Next

Y still exists only within the loop but increments as desired.


Trader3564(Posted 2008) [#28]
Since this topic is still going on, may i add:

How do i declare private fields and methods in an TType?


Gabriel(Posted 2008) [#29]
You can't. There is no such thing in BlitzMax.


Trader3564(Posted 2008) [#30]
was afraid so, ah well... its a minor thing. :)


Czar Flavius(Posted 2008) [#31]
was afraid so, ah well... its a minor thing. :) 


Oh no.. that's the secret incantation to envoke the wrath of the OOP gods!


TomToad(Posted 2008) [#32]
Oh no.. that's the secret incantation to envoke the wrath of the OOP gods!

I thought the secret incantation was
#Label
Goto Label

:D


Dreamora(Posted 2008) [#33]
Strict, SuperStrict -> goto disabled

Labels can only be used as looplabels and then with Continue LoopLabel / Exit LoopLabel :D


Trader3564(Posted 2008) [#34]
Got another point. When in a method or function, when i return a value. It automaticly stops there right? Or does it pass the return, and finished the method or function?


ziggy(Posted 2008) [#35]
return exits the function of method. It can also be used on functions or methods that doesn't return any value, to force a 'exit function' or 'exit method' operation


Czar Flavius(Posted 2008) [#36]
Try this. Think about how it would work in the two possibilities.

Strict

For Local a = 0 To 13
	Print a + " is it prime? " + isprime(a)
Next
End

Function isprime:Int(number)
	If number < 2 Then Return False
	Local maxfactor = number/2
	For Local factor = 2 To maxfactor
		If Not (number Mod factor) Then Return False
	Next
	Return True
End Function



ImaginaryHuman(Posted 2008) [#37]
As discussed here:

http://www.blitzbasic.com/Community/posts.php?topic=56598#629234

Locals do end up in CPU registers where possible and Globals end up in main memory. Hence the speedup.