Общие таблицы
С числами и строками = копирует значение. После local b = a изменение b не меняет a:
local a = 5
local b = a
b = b + 1
print(a, b)5 6С таблицами всё иначе. Переменная хранит не саму таблицу, а только ссылку на неё: что-то вроде адреса таблицы в памяти компьютера. Это и есть 0x… в том, что выводит print(t). local b = a копирует ссылку, а не таблицу, поэтому обе переменные ведут к одной и той же таблице:
local prices = {carrot = 5, potato = 8}
local joePrices = prices
joePrices.carrot = 6
print(prices.carrot)
print(prices == joePrices)6
trueДедушка Джо изменил «свою» цену, и цена Эммы тоже изменилась, потому что таблица одна, а имён у неё два. А == для таблиц спрашивает, та ли это самая таблица, а не одинаково ли у двух таблиц содержимое. Каждые {} создают новую таблицу, поэтому:
print({} == {})
print({carrot = 5} == {carrot = 5})false
falseЧтобы сравнить содержимое двух таблиц, сравните их ключи и значения сами, например в цикле.
То же происходит, когда вы передаёте таблицу в функцию. Параметр ссылается на ту же таблицу, поэтому функция может её изменить, и изменение будет видно снаружи. Часто это именно то, что нужно; такой функции даже не обязательно что-то возвращать:
local function harvest(barn, crop, amount)
barn[crop] = (barn[crop] or 0) + amount
end
local barn = {}
harvest(barn, "carrot", 12)
harvest(barn, "carrot", 3)
print(barn.carrot)15Когда нужна отдельная таблица, её нужно скопировать: создать новую таблицу и перенести в неё каждый ключ и значение через pairs:
local function copy(t)
local result = {}
for key, value in pairs(t) do
result[key] = value
end
return result
end
local prices = {carrot = 5, potato = 8}
local joePrices = copy(prices)
joePrices.carrot = 6
print(prices.carrot, joePrices.carrot)
print(prices == joePrices)5 6
falseФункция работает и для списков, потому что pairs проходит и по ключам 1, 2, 3… Но копирует она только один уровень: если значение само является таблицей, как амбар в farm.barn, то копия получит ссылку на ту же вложенную таблицу.
Задание
- 1
Запустите программу: цены Эммы тоже изменились, потому что
hugoPrices— это та же таблица, что иprices. Напишите функциюcopy(t), которая возвращает новую таблицу с теми же ключами и значениями, и сделайтеhugoPricesкопиейprices. Тогда программа выведет:Эмма: морковь 5, картофель 8, тыква 20 Гуго: морковь 7, картофель 8, тыква 25 - 2
В конце программы напишите функцию
raise(t, amount), которая прибавляетamountк каждой цене в полученной таблице: она меняет эту таблицу и ничего не возвращает. Повысьте цены Гуго на 1 и покажите оба списка цен снова:Эмма: морковь 5, картофель 8, тыква 20 Гуго: морковь 8, картофель 9, тыква 26