Точка таблицы на другой стол в Lua
Есть ли способ указать таблицу на другую таблицу? например:
local a = {}
local b = {}
a.name = "Josh"
print(a.name) -- Prints 'Josh'
print(b.name) -- Prints 'Josh' aswell
a.name = "I don't have a name"
print(a.name) -- Print 'I don't have a name'
print(b.name) -- Prints 'I don't have a name' aswell
Я надеюсь, что вы поняли мою точку зрения.. спасибо
РЕДАКТИРОВАТЬ:
Итак, вот идея:
Я делаю динамическую функцию, которая такова
local table = { 1, 2, "hey" }
function drawimage(name, posx, posy referencetable)
_tabledata[name] = { posx = posx, posy = posy, reference = {}}
setmetatable(_tabledata[name].reference, { __index = referencetable })
end
drawimage("Header", 0, 50, table)
Все хорошо, хорошо, значения работают, и мы все счастливы. Проблема возникает, когда справочная таблица меняет свое значение таким образом.
local data = { 123123, 545454, "heyou" } -- Data is sent from another script via a trigger
table = data
Так как я не обновляю его по индексной (то есть: table[1] = 9999) ссылочной переменной "несинхронизировано" с реальной, я надеюсь, вы понимаете:)
EDIT2:
Хорошо, вот пример моей главной проблемы
local maintable = { "Stack", "Overflow" }
local maintablecopy = {}
maintablecopy = maintable
print("maintable[1] = " ..maintable[1]) -- Prints Stack
print("maintable[2] = " ..maintable[2]) -- Prints Overflow
print("")
print("maintablecopy[1] = " ..maintablecopy[1]) -- Prints Stack
print("maintablecopy[2] = " ..maintablecopy[2]) -- Prints Overflow
print("")
print("Changing values..")
local newdata = { "Hello", "World" }
maintable = newdata
print("")
print("maintable[1] = " ..maintable[1]) -- Prints Hello
print("maintable[2] = " ..maintable[2]) -- Prints World
print("")
print("maintablecopy[1] = " ..maintablecopy[1]) -- Prints Stack -- PROBLEM
print("maintablecopy[2] = " ..maintablecopy[2]) -- Prints Overflow -- PROBLEM
print("Using setmetatable..")
maintable = { "Stack", "Overflow" }
maintablecopy = {}
setmetatable(maintablecopy, { __index = maintable })
print("maintable[1] = " ..maintable[1]) -- Prints Stack
print("maintable[2] = " ..maintable[2]) -- Prints Overflow
print("")
print("maintablecopy[1] = " ..maintablecopy[1]) -- Prints Stack
print("maintablecopy[2] = " ..maintablecopy[2]) -- Prints Overflow
print("")
print("Changing values..")
local newdata = { "Hello", "World" }
maintable = newdata
print("")
print("maintable[1] = " ..maintable[1]) -- Prints Hello
print("maintable[2] = " ..maintable[2]) -- Prints World
print("")
print("maintablecopy[1] = " ..maintablecopy[1]) -- Prints Stack -- PROBLEM
print("maintablecopy[2] = " ..maintablecopy[2]) -- Prints Overflow -- PROBLEM
Почему я не могу напрямую указать это на таблицу, когда переменная обновляется? потому что у меня есть 20 таблиц для обновления, было бы проще сделать это
local _dynamics = {}
local tbl1 = { "Hey", 8787 }
local tbl2 = { 123, "There" }
local tbl3 = { "You", 1111 }
function dynamicFunction(name, posx, posy, textsize, reference)
_dynamics[name] = { posx = posx, posy = posy, textsize = textsize, reference = reference }
end
dynamicFunction("first", 0, 0, 5, tbl1)
dynamicFunction("second", 0, 0, 5, tbl2)
dynamicFunction("third", 0, 0, 5, tbl3)
for key in pairs(_dynamics) do
local inf = _dynamics[key]
for i = 1, #inf.reference do
print(inf.reference[i])
if i == #inf.reference then
print("")
end
end
end
print("")
print("")
tbl1 = { "aaaaa", "bbbbbbbbbb" }
tbl2 = { "ccccccccccc", "ttttttttttt" }
tbl3 = { "rrrrrrr", "yyyyyyyyyyy" }
for key in pairs(_dynamics) do
local inf = _dynamics[key]
for i = 1, #inf.reference do
print(inf.reference[i])
if i == #inf.reference then
print("")
end
end
end
print("Values should get updated on the reference variable, but it doesn't.. this would save me to do a check for every single variable")
Вы можете запустить его на http://www.compileonline.com/execute_lua_online.php чтобы понять, что я имею в виду.
Извините, если это беспорядок, но мой английский не самый лучший:D
1 ответ
Вы хотите __index
метаметод:
local a = { name="Josh" }
local b = {}
print(a.name) --> Josh
print(b.name) --> nil
setmetatable(b,{__index=a})
print(b.name) --> Josh
a.name = "Gilligan"
print(a.name) --> Gilligan
print(b.name) --> Gilligan
-- but note! the shadow
b.name = "overridden"
print(a.name) --> Gilligan
print(b.name) --> overridden
b.name = nil
print(a.name) --> Gilligan
print(b.name) --> Gilligan
Для более подробной информации, я предлагаю эту статью:
http://phrogz.net/lua/LearningLua_ValuesAndMetatables.html
Ответ на Edit2:
Позвольте мне обобщить проблемы с некоторыми из вашего кода:
local maintablecopy = {}
maintablecopy = maintable
С помощью приведенного выше кода вы создаете одну таблицу, установите maintablecopy
ссылаться на эту таблицу, а затем вы полностью откажетесь от нее, когда вы установите maintablecopy
вместо этого ссылаться на другую таблицу. Это демонстрирует отсутствие понимания того, как работают переменные.
local newdata = { "Hello", "World" }
maintable = newdata
Опять вы не "копируете" newdata
в maintable
, вы меняете переменную для ссылки на ту же таблицу здесь.
maintable = { "Stack", "Overflow" }
maintablecopy = {}
setmetatable(maintablecopy, { __index = maintable })
-- …
local newdata = { "Hello", "World" }
maintable = newdata
Опять та же проблема. Вот несколько способов изменить ваш код:
Заменить содержимое таблицы
Вместо maintable = newdata
Вы могли бы сделать это:
function copytable(from,to_table)
-- erase all old keys
for k,_ in pairs(to_table) do to_table[k] = nil end
-- copy the new ones over
for k,v in pairs(from) do to_table[k] = v end
end
local a = { name="Foo" }
local b = {}
copytable(a,b)
print(a.name == b.name) --> true
local c = { name="NEW" }
copytable(c,b)
print(c.name == b.name) --> true
Однако это не приведет к b
обновить, если c
изменения.
c.name = "EVEN NEWER"
print(c.name == b.name) --> false
Обновите __index
local a = { name="Foo" }
local b = setmetatable({},{__index=a})
print(a.name == b.name) --> true
-- cause b to follow c now instead of a
local c = { name="NEW" }
getmetatable(b).__index = c
print(c.name == b.name) --> true
c.name = "EVEN NEWER"
print(c.name == b.name) --> true
В общем, вам нужно сделать шаг назад и описать исходную проблему, которую вы пытаетесь решить, вместо этой проблемы XY.