1

Issue

While trying to learn lua I accidentally found out that if

a = {"a"}
b = a

than this produces (no surprise):

a
{"a"} --[[table: 0x046bde18]]
b
{"a"} --[[table: 0x046bde18]]

but then if:

a[2] = "b"

why is a == b still true?

a
{"a", "b"} --[[table: 0x046bde18]]
b -- this is a surprise
{"a", "b"} --[[table: 0x046bde18]]

This seem to work both ways: if a new value is assigned to b then it will be also assigned to a.

On the other hand if I assign a a value (example: a = 1) and b = a then if a value is changed (a = 2) then b retains the original value (still b = 1).

Questions

  1. Why is this behaviour different depending on wheather a is an array/table or a value? Is it due to built-in metatables (__newindex)?
  2. What is the purpose of such behaviour of arrays/tables?
  3. What if I wanted/needed to somehow seperate a and b (or what to do if I wanted to store the values of a before changing b)?

(I read Lua Assignment and Metatables and Metamethods chapters of the Lua Reference Manual but still have no clue why such behaviour occures.)

Siemkowski
  • 1,351
  • 5
  • 15
  • 32
  • Why is this such a common problem. All you're doing is assigning variable b to the value a is assigned, b just points to the same thing a points to. – warspyking Feb 01 '17 at 16:48
  • @warspyking as a novice programmer I find it counter intuitive (but justifiable as explained in the answer) – Siemkowski Feb 01 '17 at 17:05

1 Answers1

2

In your example, a and b are just references to the same table. In Lua, tables are objects, and you created a table and assigned it to a with the first statement, and then you created a second reference to the same table with the second assignment. So, both a[2] = "b" and b[2] = "b" are acting on the same underlying table (table: 0x046bde18).

A table is not a value, it is an object. a = {"a"} constructs a table and assigns a reference to the table to a. b = a assigns the same reference to b. But, x = 10 assigns the value 10 to x. If y = 10 and you could change the underlying value of 10, I suppose that this change would be reflected in both x and y, but I know of no obvious way to do this. In this code:

x = 10
y = 10
y = y + 1

the resulting values will be x = 10, and y = 11. The underlying value of 10 has not changed, but y was reassigned to the value 11.

If you want to work with two copies of the table that can change independently, you would need to write a function that copies the members of a into b = {}. Here is a question that discusses making copies of tables.

Community
  • 1
  • 1
ad absurdum
  • 19,498
  • 5
  • 37
  • 60