Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Lua huh wha? : I don't understand how this assignment is working

edited January 2013 in General Posts: 557

Here's my code:

    testVariable = "prime rib"

    --a function that replaces a target with a string:
    replacer = function (target, string)
        target = string
        --below should show the target as having the string's value:
        print(target)
    end

    replacer(testVariable,"finger food")

    --below should also show the target as having the string's value, right?
    print (testVariable)

Here's the output:

finger food
prime rib

Shouldn't both the outputs be "finger food?" I must be missing something important here.

Tagged:

Comments

  • edited January 2013 Posts: 502

    Functions in lua are using call-by-value, so you don't send a pointer to your variable into the function.

    If you send in an table, you can modify it's contents in the function


    x = {a="a"} function replacer(target, string) target.a = string end replacer(x, "hello")
  • So, when you say "call-by-value" that means that a variable for a string gets turned into the string itself when used in a function call? Wow that might also clear up a lot of other problems I'm seeing.

  • Posts: 2,161

    Actually, I'd say it's better to think of things the other way around. Everything in lua is a pointer. The key is that everything gets dereferenced automatically and as much as possible.

    So let's go through the code:

    testVariable = "prime rib"
    

    Lua creates a string object, which is a memory address, sticks the string "prime rib" in there. testVariable contains a pointer to this address.

    replacer(testVariable,"finger food")
    

    This calls the function replacer (or rather, the function that replacer points to!) with two pointers. One is a pointer to "prime rib", the other is a pointer to "finger food" (which has been created on the fly).

    replacer = function (target, string)
    

    Here's the function definition, but let us imagine it being called as above. When we call replacer(testVariable, "finger food") then lua does effectively:

    do -- to cordon off the function
        local target = testVariable
        local string = "finger food"
    

    The important bit here is target = testVariable. This makes target a copy of testVariable. Recall that testVariable was a pointer to "prime rib", so now target is also a pointer to "prime rib". But, and this is the crucial part, there is no link between target and testVariable. In particular, target is not a pointer to testVariable, but target is a pointer to what testVariable is a pointer to. Thus in:

    local target = testVariable
    

    the examination of testVariable leads to it being dereferenced, whence this means:

    local target = <whatever testVariable is pointing to>
    

    Let's continue:

    target = string
    

    So now target points to whatever string pointed to (namely "finger food"), but this assignment has done nothing to testVariable since there is no link between target and testVariable.

    @tnlogy's suggestion of using tables is a good one and one that I frequently use. I have many functions of the form:

    function do_something_to(t)
        t.field = 32
    end
    

    so that I can write do_something_to(my_table).

    The point here being that t points to the same thing that my_table points to: a table. So manipulating that table via t affects the same thing that my_table points to.

    This doesn't work with strings because strings are immutable. So you can't sneak in to lua's memory and replace "prime rib" with "finger food": it won't let you. Any time that you think you are manipulating a string then you are actually creating a new string and updating the pointer to point to the new one.

    One way to do what your code would like to do is to manipulate the _G table:

    testVariable="prime rib"
    replacer = function(target,source)
      _G[target] = source
      print(_G[target])
    end
    replacer("testVariable","finger food")
    -> finger food
    print(testVariable)
    -> finger food
    

    But notice that I pass the name of the variable, not the variable itself.

  • Wow, Andrew, thanks for that.

Sign In or Register to comment.