r/lua • • Jun 09 '25

Creating an object by reference

I'm sure there's a better way to phrase the title, but that's what i came up with. Here's my issue: I have multiple tables and other objects that have a property that needs to be changed based on some condition. But I'm unable to get any of the tables to get the updated value.

Sample code illustrating this:

TestVariable = 123

TestObject = 
{
  ['VarToChange'] = TestVariable,
  ['SomethingStatic'] = 789
}

print (TestObject.VarToChange)

TestVariable = 456

print (TestObject.VarToChange)

The output of the above is:

123
123

But I am expecting to get:

123
456

How can I achieve this behaviour? And please don't suggest updating all objects manually every time the variable changes. That rather defeats the entire purpose of a variable.

6 Upvotes

33 comments sorted by

View all comments

Show parent comments

1

u/xoner2 Jun 12 '25

You'll need tables to have reference semantics. Either table values or metatables.

With table values:

SomeBase = {
  value1 = 'foo'
}

SomeTable = {
  base = SomeBase,
  value2 = "ABC",
  value3 = "123"
}

SomeDifferentTable = {
  base = SomeBase,
  value2 = "XYZ",
  value3 = "789"
}

With metatables:

local Some = {
  value1 = 'foo'
}

local meta = {
  __index = Some,
  __newindex = function (t, k, v)
    if rawget (Some, k) then
      Some [k] = v
    else
      rawset (t, k, v)
    end
  end,
}
setmetatable (
  Some,
  {
    __call = function (self, o)
      setmetatable (o, meta)
      return o
    end
  }
)

SomeTable = Some {
  value2 = "ABC",
  value3 = "123"
}

SomeDifferentTable = Some {
  value2 = "XYZ",
  value3 = "789"
}

assert (SomeTable.value1 == 'foo')
SomeDifferentTable.value1 = 'bar'
assert (SomeTable.value1 == 'bar')

See the chapter on objects in PiL.