Метатабличная проблема

Итак, я знаю, что lua будет искать метатаблицу таблицы, если она не содержит переменной, на которую я ссылаюсь, но кажется неправильным, что когда я пытаюсь установить переменную, которая еще не существует в таблице, вместо этого она устанавливает ее в метатаблицу. .

Вот пример того, что я имею в виду

a = {__index = {tbl1 = {var = 1}, tbl2 = {var = 2}}}
b = setmetatable({}, a)
print(b.tbl1.var, a.__index.tbl1.var)
b.tbl1.var = 2
print(b.tbl1.var, a.__index.tbl1.var)

В этом коде он заменит переменную метатаблиц вместо того, чтобы устанавливать ее в таблице, на которую я ссылаюсь.

Однако этого не происходит с этим кодом

a = {__index = {4, 5, 6}}
b = setmetatable({}, a)
print(b[1], a.__index[1])
b[1] = 2
print(b[1], a.__index[1])

Требуется ли дополнительная работа при использовании метатаблиц и вложенных таблиц? Или есть способ обойти это?


person Saana    schedule 24.08.2014    source источник


Ответы (1)


В этом коде он заменит переменную метатаблиц вместо того, чтобы устанавливать ее в таблице, на которую я ссылаюсь.

Я думаю, этого следовало ожидать; код извлекает ключ tbl1 и устанавливает поле в таблице, связанное с этим ключом. Ключ не существует в таблице, только в метатаблице, так что там он установлен. Если вы добавите тот же ключ в таблицу b = setmetatable({tbl1 = {}}, a), вы увидите, что значение установлено в этой таблице.

Требуется ли дополнительная работа при использовании метатаблиц и вложенных таблиц? Или есть способ обойти это?

Я не уверен, какой результат вы ожидаете. Lua не выполняет автоживификацию, что заставило бы tbl.foo = 1 создать таблицу tbl, если это еще не сделано. существует. Если поле tbl1 уже присутствует в таблице, поведение будет именно таким, как вы ожидаете. Если он присутствует в метатаблице и вы изменяете его поле, это именно то место, где оно будет изменено.

person Paul Kulchenko    schedule 25.08.2014
comment
Если я использую b = setmetatable({tbl1 = {}}, a), он не наследует значение метатаблицы и вместо этого возвращает nil, что противоречит цели метатаблицы в этом контексте. - person Saana; 25.08.2014
comment
Это именно то, что вы получаете: если в вашей таблице нет ключа tbl1, вы получаете его значение по умолчанию (из метатаблицы). Если вы попытаетесь изменить значения в таблице, которую вы получили на основе ссылки на ключ tbl1, они будут изменены в этой таблице. Вот почему я спросил, что вы пытаетесь сделать или избежать. Если вы хотите избежать изменений в таблице, сохраненной как значение для ключа tbl1, вам может потребоваться установить метатаблицу для этой таблицы. - person Paul Kulchenko; 25.08.2014