Lua multiple assignment with tables

前端 未结 4 1899
伪装坚强ぢ
伪装坚强ぢ 2021-01-12 08:36

This code:

function foo()
    return 1, 2, 3
end

bar = {}

bar = {a, b, c = foo()}

produces:

bar.a = nil
bar.b = nil
bar.c         


        
相关标签:
4条回答
  • 2021-01-12 08:58
    bar = {}
    bar.a, bar.b, bar.c = foo()
    
    0 讨论(0)
  • 2021-01-12 09:05
    bar = {}
    local abc = foo()
    bar.a, bar.b, bar.c = abc, abc, abc
    

    Simply bar.a, bar.b, bar.c = foo() will only set bar.a to foo(), the other two will be set to nil because they get set to the second and third values respectively, and you've only given one value.

    0 讨论(0)
  • 2021-01-12 09:09

    If you can, have foo() return a table formatted the right way.

    function foo()
        return {a = 1, b = 2, c = 3}
    end
    
    bar = foo()
    
    0 讨论(0)
  • 2021-01-12 09:10

    BLUF

    There's no straight forward or elegant way to do this. You'll have to do it manually like this

    local r = { f() }           --> store all returned values in r
    local bar = { }
    local c = string.byte 'a'   --> start with 'a'
    for _, v in ipairs(r) do
       local t = string.char(c)
       bar[t] = v               --> assign each value to respective letter
       c = c + 1
    end
    

    If you'd had a, b, c = foo() you'd get all the three values assigned to the three variables. However, you've

    bar = { a, b, c = foo() }
    

    This table constructor expression will get interpreted as the keys a, b, c getting inserted into the table, with only the last key having an associated value (aside: keys with no associated value are taken as nil; hence a and b never get inserted). Since there's only one variable to take the values returned by foo, except the first everything else it returns are discarded.

    Alternatively bar = { foo() } will assign all values returned by foo as array values of bar. However, the key to access these would [1], [2], etc. and not 'a', 'b', etc.

    Read below to know when the returned values get discarded and when they don't.


    TL;DR All returned values are retained only when the function call is the last/only expression in a list of expressions; elsewhere all except the first are discarded.

    Function call as a statement

    In Lua, when we return multiple results from a function, all of them get discarded if the function call is a statement by itself.

    foo()
    

    will discard all three return values.

    Function call in an expression

    If it's used in an expression, only the first will be retained and everything else will be discarded.

    x = foo() - 1
    print(x)        -- prints 0; the values 2, 3 are discarded
    

    Function call in an expression list

    The entire list of values returned is retained only when the call appears as the last/only item in a list of expressions. Such list of expressions occur at four places in Lua:

    1. Multiple assignment

      E.g. local a, b, c, d = 0, f(). Here b, c, d get the values 1, 2, 3 respectively.

    2. Table constructor

      E.g. local t = { 0, f() }. All values returned by f are put into t following the first 0.

    3. Function call arguments

      E.g. g(a, f()). g would receive 4, not 2, arguments. a and the three values from f.

    4. return statement

      E.g. return 'a', f(). Additional to the string 'a', all values returned by f will be received at the calling end.

    In all these situations, had f appeared not as the last expression in the list or wasn't the only expression, then all values it returned except the first would've been discarded.

    Multiple assignment statement

    In the multiple assignment statement, when the number of values assigned is lesser than number of variables, the extra variables be assigned to nil. When it's the other way around i.e if the number of variables are lesser, the extra values are discarded.

    a, b, c = 1, 2         -- a = 1, b = 2, c = nil
    a, b, c = 1, 2, 3, 4   -- 4 gets discarded
    
    0 讨论(0)
提交回复
热议问题