Функции в таблицах
В уроке о таблицах как словарях вы описывали одну вещь одной таблицей — записью вроде {name = "Морковь", days = 3}. В уроке о функциях вы узнали, что функция — такое же значение, как число или строка: её можно сохранить в переменную и передать другой функции. Соедините одно с другим, и таблица сможет хранить функции рядом с данными:
local farm = {name = "ферма Подсолнух", coins = 120}
farm.describe = function(f)
print(f.name .. ", монеты: " .. f.coins)
end
farm.describe(farm)Он выводит:
ферма Подсолнух, монеты: 120farm.describe = function(f) … end сохраняет функцию под ключом describe, точно так же как farm.coins = 120 сохраняет число под ключом coins. В farm.describe(farm) выражение farm.describe достаёт функцию из таблицы, а скобки её вызывают. Функция получает ферму как параметр f и читает её значения.
В Lua есть более короткая запись того же самого, и вы будете встречать её гораздо чаще: function farm.describe(f) означает ровно то же, что farm.describe = function(f). Перед ней нет local, потому что функция не становится новой переменной: она попадает в таблицу farm, которая уже существует. В следующем примере используется короткая запись, и он же показывает, что функция в таблице может изменить таблицу, которую получила:
local farm = {name = "ферма Подсолнух", coins = 120}
function farm.describe(f)
print(f.name .. ", монеты: " .. f.coins)
end
function farm.earn(f, amount)
f.coins = f.coins + amount
end
farm.earn(farm, 30)
farm.describe(farm)Он выводит:
ферма Подсолнух, монеты: 150Зачем передавать функции ферму параметром, если она могла бы просто взять farm? Затем, что так она работает с любой таблицей с такими же ключами: farm.describe({name = "ферма дедушки Джо", coins = 80}) выводит ферма дедушки Джо, монеты: 80. Это скоро пригодится, когда будет много таблиц одного вида.
Таблицы с функциями вы используете с самого начала курса. string и math — обычные таблицы, а string.upper — функция, которая лежит в таблице string под ключом upper:
print(type(string), type(string.upper), type(math.floor))Он выводит:
table function functionТаблица, которая хранит данные вместе с функциями для работы с ними, называется объектом. Весь этот урок — об объектах: как их писать, как создавать много однотипных и как сделать так, чтобы они работали с print, ==, < и +.
Типичная ошибка: забыть аргумент. В farm.describe() параметр f не получает значения, поэтому он равен nil:
local farm = {name = "ферма Подсолнух", coins = 120}
function farm.describe(f)
print(f.name .. ", монеты: " .. f.coins)
end
farm.describe()Программа завершается с ошибкой:
main.lua:4: attempt to index a nil value (local 'f')Индексирование — это чтение ключа через . или [ ]. f.name пытается прочитать ключ name у f, а у nil читать нечего.
Задание
- 1
В сарае Эммы лежат яйца и стоит молоко. Добавьте функцию
barn.report(b), которая выводит, что находится в сараеb, и вызовите её черезbarn.report(barn). Программа выводит:В сарае: яйца 12, молоко 4 л - 2
Добавьте функцию
barn.addEggs(b, count), которая добавляетcountяиц в сарайb. - 3
Куры снесли ещё 6 яиц. В конце программы добавьте их через
barn.addEggs(barn, 6)и снова выведите отчёт:В сарае: яйца 12, молоко 4 л В сарае: яйца 18, молоко 4 л