Page 1 of 2

Confused about assignments

Posted: Tue Jan 30, 2018 8:37 am
by hasen
I've been studying various bits of code I found around the place and on this forum and I was slightly confused about the assignments going on in one block I came across:

Code: Select all

player.x, player.y, cols, len = world:move(player, player.x + player.dx, player.y + player.dy)

    player.xAcc, player.yAcc = 0, player.yAcc * 0.45
I'm aware that you can make assignment like this in lua:

Code: Select all

SW, SH = 10, 12
But the above assignments seem to be slightly different. I'm not sure what's getting assigned to what in these lines.

Re: Confused about assignments

Posted: Tue Jan 30, 2018 9:01 am
by grump
But the above assignments seem to be slightly different. I'm not sure what's getting assigned to what in these lines.
The right side of an assignment is always assigned to the left side. There can only be variables on the left, while the right side can be arbitrary expressions. Lua evaluates all expressions on the right side (going from left to right) and assigns the results to the variables on the left (also from left to right).

Code: Select all

left1, left2, left3 = expression1, expression2, expression3
hasen wrote: Tue Jan 30, 2018 8:37 am

Code: Select all

player.x, player.y, cols, len = world:move(player, player.x + player.dx, player.y + player.dy)
Functions in Lua can have more than one return value. The function world:move() probably returns 4 values. This line assigns these values to the variables player.x, player.y, cols and len.

Code: Select all

player.xAcc, player.yAcc = 0, player.yAcc * 0.45
Same here, just without the function call. player.xAcc is set to 0, player.yAcc is set to player.yAcc * 0.45. It's equivalent to

Code: Select all

player.xAcc = 0
player.yAcc = player.yAcc * 0.45

Re: Confused about assignments

Posted: Tue Jan 30, 2018 9:16 am
by hasen
grump wrote: Tue Jan 30, 2018 9:01 am
But the above assignments seem to be slightly different. I'm not sure what's getting assigned to what in these lines.
The right side of an assignment is always assigned to the left side. There can only be variables on the left, while the right side can be arbitrary expressions. Lua evaluates all expressions on the right side (going from left to right) and assigns the results to the variables on the left (also from left to right).

Code: Select all

left1, left2, left3 = expression1, expression2, expression3
hasen wrote: Tue Jan 30, 2018 8:37 am

Code: Select all

player.x, player.y, cols, len = world:move(player, player.x + player.dx, player.y + player.dy)
Functions in Lua can have more than one return value. The function world:move() probably returns 4 values. This line assigns these values to the variables player.x, player.y, cols and len.

Code: Select all

player.xAcc, player.yAcc = 0, player.yAcc * 0.45
Same here, just without the function call. player.xAcc is set to 0, player.yAcc is set to player.yAcc * 0.45. It's equivalent to

Code: Select all

player.xAcc = 0
player.yAcc = player.yAcc * 0.45
Ok I see, so it was like I thought, it was just that the world:move was returning four values. And for the second one it seems obvious now, don't know why I didn't get that before. Thanks very much for your help.

Re: Confused about assignments

Posted: Tue Jan 30, 2018 9:45 am
by zorg
hasen wrote: Tue Jan 30, 2018 9:16 am
grump wrote: Tue Jan 30, 2018 9:01 am ...
Ok I see, so it was like I thought, it was just that the world:move was returning four values. And for the second one it seems obvious now, don't know why I didn't get that before. Thanks very much for your help.
Keep in mind two more things;
lua functions can return more than one value (without using tables, i mean)
the comma (as well as extra parentheses around function calls) limit the number of returned values to 1.
So in the example code:

Code: Select all

player.x, player.y, cols, len = world:move(player, player.x + player.dx, player.y + player.dy) -- this probably returns 4 values, although there's no rule that it needs to; if it returns more than how many vars are on the left side of the equals sign, they get discarded, if it returns less, then the rightmost vars will be set to nil.

a,b = fn(), 'whatever', -- fn will return one value because of the comma
d,d = (fn()) -- fn will return one value because of the parentheses around it

Re: Confused about assignments

Posted: Tue Jan 30, 2018 11:27 am
by hasen
Ok I see, thanks for elaborating on that, Zorg. That would make sense since in Lua anything that isn't something get's labeled as nil. Which is pretty convenient really. Good tips regarding the functions too.

Re: Confused about assignments

Posted: Tue Jan 30, 2018 9:33 pm
by grump
Thanks zorg. Sematics of multiple return values is one of the more difficult, least intuitive parts about Lua, and it keeps messing with me to this day.

Re: Confused about assignments

Posted: Tue Jan 30, 2018 11:45 pm
by pgimeno
By the way, that applies to parameters in function calls too. Only the last element can see multiple values, e.g.

Code: Select all

function f()
  return 1, 2
end

function g(a,b,c,d)
  print(a,b,c,d)
end

g(f(),f(),f()) -- prints 1,1,1,2
w,x,y,z = f(), f(), f() -- w=1 x=1 y=1 z=2
w,x,y,z = f(), f(), (f()) -- w=1 x=1 y=1 z=nil

Re: Confused about assignments

Posted: Wed Jan 31, 2018 12:21 am
by zorg
I think it's correct to say, that in anything that features commas as variable delimiters; tables, function (even anonymous and "functionalized table via metatable") parameters, and parentheses around a multi-value returning construct will have its return values trimmed to one.

Code: Select all

function myprint(t)
    for i,v in ipairs(t) do io.write(tostring(v)) end
    io.write('\n')
end

myprint({1,2,(function() return 3,4 end)()}) -- table + anon function at the end, not wrapped in parentheses --> 1,2,3,4
myprint({1,2,(function() return 3,4 end)(),5}) -- table + anon function not at the end, not wrapped in parentheses --> 1,2,3,5
myprint({1,2,((function() return 3,4 end)())}) -- table + anon function at the end, wrapped in parentheses --> 1,2,3
myprint({1,2,((function() return 3,4 end)()),5}) -- table + anon function not at the end, wrapped in parentheses --> 1,2,3,5

-- and just for some extra shenanigans, parameters to the anonymous function while it's at the last table slot

myprint({1,2,(function(a,b) return a,b end)(3,4)}) --> 1,2,3,4
myprint({1,2,(function(a,b) return a,b end)(3)}) --> 1,2,3
myprint({1,2,(function(a,b) return a,b end)(nil,4)}) --> 1,2,nil,4
myprint({1,2,(function(a) return a end)(3,4)}) --> 1,2,3
myprint({1,2,(function(a) return a end)(nil,4)}) --> 1,2

Re: Confused about assignments

Posted: Thu Sep 12, 2019 8:38 am
by choopos
Here's my solution to the problem https://www.assignmentexpert.com/progra ... ce-project. They haven't break my trust yet.

Re: Confused about assignments

Posted: Thu Sep 12, 2019 9:39 am
by Sasha264
Is here an explanation why the comma limits the number of returned values to 1?

I can imagine negative side of that solution. For example this call:

Code: Select all

love.graphics.draw(drawable, x, y, r, sx, sy, ox, oy, kx, ky)
can not be made like this:

Code: Select all

love.graphics.draw(drawable, obj:getPosition(), r, obj:getScale(), ox, oy, kx, ky)
instead it requires a bunch of temp variables.

But what is positive side?