Navigation

    Fuze Arena Logo
    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Popular
    • Users
    • Groups
    • Help
    • Discord

    Instant karma on misplaced for loop

    Beginners
    4
    6
    413
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • spikey
      spikey F last edited by spikey

      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_9

      When 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.

      1 Reply Last reply Reply Quote 0
      • Zero Division
        Zero Division last edited by

        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.

        1 Reply Last reply Reply Quote 0
        • spikey
          spikey F last edited by

          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 this

          int i;
          for (i = 0 ; i < 4 ; i++) {
          }
          

          ..and so, it is probably not a bug, because i will then be valid globally.

          1 Reply Last reply Reply Quote 0
          • Martin
            Martin Fuze Team last edited by

            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.

            1 Reply Last reply Reply Quote 3
            • PB____
              PB____ last edited by PB____

              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.

              PB____ 1 Reply Last reply Reply Quote 2
              • PB____
                PB____ @PB____ last edited by

                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 using var 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.
                1 Reply Last reply Reply Quote 2
                • First post
                  Last post