Quick Links: Download Gideros Studio | Gideros Documentation | Gideros community chat | DONATE
Global variable - local variable — Gideros Forum

Global variable - local variable

loves_oiloves_oi Member
edited September 2012 in General questions
function x()
     y = 3
     function z()
        u = 5
	print (u)
     end
 
     local a = 3
     local function b()
        c = 5
	print (c)
     end 
end
 
print (z())  ---error
print (y)    ---error
It is said that variable y and function z is global . Then , why do i take error while i am trying to access it??
Thanks in advance

Dislikes: Yan

+1 -1 (+0 / -1 )Share on Facebook

Comments

  • hnimhnim Member
    edited September 2012
    @love_oi, because y and z is created in function x(), but you didnt call x so y and z is nil

    Likes: atilim

    +1 -1 (+1 / -0 )Share on Facebook
  • john26john26 Maintainer
    edited September 2012
    The second statement, print (y) will work ok. It just prints nil.

    It's important to realise that Lua does not "look ahead" and initialise global variables before it processes a file. Global variables are available anywhere but are not auto-initialised in any way. For instance
    x=y
    y=2
    print (x,y)
    prints "nil,2".

    The other thing to notice is that functions are first class values in Lua, they are not special like in other languages. The statement
    function foo(a)
      print (a)
    end
    is equivalent to
    foo=function (a)
      print (a)
    end
    which makes it clearer that function assignment is the same as variable assignment. Setting foo=function (a)... is the same as setting foo=5. So this code will give an error.
    x=2
    print (x,foo(2)) -- error
     
    foo=function (a)
      print (a)
    end
    Although foo is a global variable, the foo assignment has not been done when we call foo, so foo has value nil and it is illegal to call such a value. Of course, all is well if rearrange
    foo=function (a)
      print (a)
    end
     
    x=2
    print (x,foo(2)) -- output: 2,2
    Now consider this example
    x,y,foo,bar=nil,nil,nil,nil
     
    function foo(a)
      print (bar(a+1))
    end
     
    function bar(a)
      return a*2
    end
     
    x=y
    y=2
    print (x,y,foo(2))   -- prints 6, nil, 2
    Note I've set x,y,foo and bar to nil at the beginning. There's no need to do this but I find it helps me remember what globals I've got. Foo and bar are declared before they are called so that's fine. But notice that when the interpreter is initialising foo, bar is referred before we have set it up. That's fine: it's only when a function is called that it needs to be non-nil. However, if you make bar local this wont work.
    function foo(a)
      print (bar(a+1))  --Error attempt to call global 'bar' (a nil value)
    end
     
    local function bar(a)
      return a*2
    end
     
    x=y
    y=2
    print (x,y,foo(2))
    I'm not sure why!
  • john26john26 Maintainer
    Going back to your original example
    function x()
         y = 3
         function z()
            u = 5
    	print (u)
         end
     
         local a = 3
         local function b()
            c = 5
    	print (c)
         end 
    end
     
    x()
    z()  -- output: 5
    print (u,y,c,a) -- output: 5 3 nil nil
    Because we actually call x(), globals z(), u and y are set up. a is local so is destroyed when x() returns. c is global but is never set since b() is never called.
  • techdojotechdojo Guru
    edited September 2012
    However, if you make bar local this wont work.
    function foo(a)
      print (bar(a+1))  --Error attempt to call global 'bar' (a nil value)
    end
     
    local function bar(a)
      return a*2
    end
     
    x=y
    y=2
    print (x,y,foo(2))   
    I'm not sure why!
    I'll take a stab at this.

    If you put the local function bar() before the function foo() it'll work - this is "I think" because when the parser pre-compiles foo it can't find bar (it's not been defined yet) and so assumes it's a global bar it's looking for.

    So the fact that you then have a local bar is irrelevant as foo's already looking for the global one.

    If you declare bar first (either global or local) then foo will know that bar exists within the current scope and thus generate the correct code.

    At least that's my (current) understanding.
    WhiteTree Games - Home, home on the web, where the bits and bytes they do play!
    #MakeABetterGame! "Never give up, Never NEVER give up!" - Winston Churchill
  • john26john26 Maintainer
    Actually the error does not occur until the line print(x,y,foo(2)) is reached. There is no error when function foo is precompiled as you can see if you delete the line print (x,y,foo(2)), then the program will run without error.


    Lua has no problem compiling functions which call other functions which are currently nil. It's only when a function is actually called that it needs to be defined.

    The reason foo cannot access bar when its called is because functions only have access to three things:
    1) Their arguments
    2) global variables
    3) Their upvalues

    Upvalues, or "external local variables" are local variables outside the scope of the function and defined before the function. The example can be fixed if we add the line local bar
    local bar
     
    function foo(a)
      print (bar(a+1)) 
    end
     
    function bar(a)
      return a*2
    end
     
    x=y
    y=2
    print (x,y,foo(2))
    now foo has an upvalue bar which is initially nil but will be set before we call foo.

    Upvalues and closures are among the most complex features of Lua. Personally I just declare all functions as global to avoid this sort of problem.
  • Actually the error does not occur until the line print(x,y,foo(2)) is reached. There is no error when function foo is precompiled as you can see if you delete the line print (x,y,foo(2)), then the program will run without error.
    Exactly it's not until the code is run that Lua realises that it's actually attempting to call the global bar (which is nil), adding the local bar, is a bit like making a prototype of a function (or declaring a variable as "extern") in C and is something I use a lot when dealing with event handlers.

    Upvalues and closures are among the most complex features of Lua. Personally I just declare all functions as global to avoid this sort of problem.
    Agreed :) although you can do some seriously powerful things with them - personally, I just keep everything in a module local and declare all the locals first.

    WhiteTree Games - Home, home on the web, where the bits and bytes they do play!
    #MakeABetterGame! "Never give up, Never NEVER give up!" - Winston Churchill
  • MellsMells Guru
    edited September 2012
    I often use forward declaration when I need to keep (for myself) instructions in the sequence order that feels right.
    It also helps me to avoid creating too many global variables/functions.

    Edit : same as you said, @techdojo :)
    twitter@TheWindApps Artful applications : The Wind Forest. #art #japan #apps
Sign In or Register to comment.