Instant karma on misplaced for loop
-
I was thinking I get the following output:
0:_5_6_7_8_9 1:_5_6_7_8_9 2:_5_6_7_8_9 3:_5_6_7_8_9
from this code:
for i = 0 to 4 loop print(i,":") testParam() print("\n") repeat // main loop loop update() sleep(60) repeat function testParam() // print("INCOMING:", i) for i = 5 to 10 loop print("_", i) repeat return void
But I only got:
0:_5_6_7_8_9
If you uncomment the print() inside the function, you get:
0:INCOMING:0_5_6_7_8_9When thinking about it, it makes sense: outside the main loop, the for-function declared the variable i, so it became global.
Thought I share that with you. Maybe this saves somebody a few minutes. -
Wait... so the loop counter doesn't go out of scope at the end of the for loop? That's either unusual or it's a bug.
-
The for loop inside the testParm() function changes also the i variable in the global scope. So, yes the counter does not go out of scope. But this seems to be because the for loop was placed outside of the main loop.
It seems to translate the for loop to thisint i; for (i = 0 ; i < 4 ; i++) { }
..and so, it is probably not a bug, because
i
will then be valid globally. -
Correct, in your example code, it's not a bug because as you describe, i is defined prior to the function as a global.
Where it becomes very unusual is if you change it to this:
for i = 0 to 10 loop // Do something repeat function myFunc() for i = 0 to 5 loop // Do something repeat return void
It's unsual compared to every other language that I've experienced in that I would expect the for statement in the function to reset the value of i to the initial value of the loop, being 0. BUT, being a global variable this doesn't happen, i is already greater than 5 so the loop does not execute.
I personally get around this by using unique variable names in all my functions (like _i) but i guess you could just as easily reset i to 0 just before the for loop.
Where I'd say this exhibits the behaviour of a bug is when you add len() into the equation:
array myArray[5] for i = 0 to 10 loop // Do something repeat function myFunc() for i = 0 to len(myArray) loop // Do something repeat return void
I haven't verified if this always happens but I have for sure seen instances of it where the loop is executed at least once and gives an out of bounds error on 'myArray'. There's a report of that active on the forum right now.
I think that needs further investigation. The rest is just (in my opinion at least) unusual.
-
This behavior is more common in interpreted scripts (like JavaScript). It is always good practice to explicitly declare your variables in the scope where they belong.
The following would fix it (I did test this code in Fuze, it does work):
for i = 0 to 5 loop print("\n global: ", i ); nested() repeat function nested() int i // by declaring i here, this function will use i on it's own scope (note however, that this will also prevent code in this function from accessing the global variable i ) for i = 0 to 5 loop print("nested:", i) repeat return void loop update() repeat
In any case it is a good idea to declare the variables that you intend to be scoped to the function where you use them. Because this will prevent the behavior of the function to change should you accidentally create a global variable with the same name later.
-
I have some more findings around this, that I'd gladly share here. When discussing this on Discord, @MikeDX pointed out to me that Fuze doesn't really pay attention to the type of variable. So in stead of using a specific type like
int
, I would recommend usingvar
in stead. It's not an official keyword in Fuze, but it's a common keyword in other languages where a variable is declared with a keyword, without declaring the type with it (for instance, it occurs in C# and in JavaScript)A = 1 B = 2 var n // pulls scope of n out of fn, it still needs to be assigned, but this can be done in fn now. function fn() var C = A // A still refers to global scope A, since it has not been declared in fn yet. A = 3 // Updates global A to 3 var A = 4 // declares local A and assigns it 4 without touching global A var B = 5 // same for B n = "\n" // only because n has been used outside of fn, this assigns "\n" to the global variable n. print("in:", n, A, n, B, n, C, n) // in \n 4 \n 5 \n 1 return void fn() print("out", n, A, n, B) // out \n 3 2 loop update() repeat
So in summary, this is how I'd suggest working this it:
- Always declare your variables, for the scope they are used in even if you don't assign them a value yet
- You can use
var
as if it where a keyword to declare your variable (I think that looks good and I thought that epiphany was worth a double post) - In some cases, you might want to assign a global variable to local variable before using them, but it's better to avoid ghosting your variables by using the same name locally in your function.