Функции как значения
В Lua функция — это значение, как число, строка или таблица. Об этом говорит type: type(print) равно "function". И, как любое значение, функцию можно сохранить в переменной. На самом деле local function double(n) — это просто более короткий способ создать функцию и сохранить её в локальной переменной, вот так:
local double = function(n)
return n * 2
end
local twice = double
print(double(4), twice(10))
print(type(double), type(double(4)))Программа выводит:
8 20
function numberfunction(n) … end без имени создаёт функцию, а local double = сохраняет её в переменной. local twice = double ничего не вызывает, потому что скобок нет: эта запись сохраняет ту же функцию под вторым именем. type(double) спрашивает о самой функции, а type(double(4)) — о числе, которое она вернула.
Самое полезное: функцию можно передать другой функции как аргумент. Эта функция проходит по списку и изменяет каждый элемент с помощью функции, которую получает в параметре:
local function applyToAll(list, change)
local result = {}
for _, value in ipairs(list) do
table.insert(result, change(value))
end
return result
end
local function double(n)
return n * 2
end
local prices = {2, 3, 5}
print(table.concat(applyToAll(prices, double), " "))
print(table.concat(applyToAll(prices, function(n) return n + 1 end), " "))Программа выводит:
4 6 10
3 4 6Внутри applyToAll параметр change — такой же, как любой другой, но в нём лежит функция, поэтому applyToAll её вызывает: change(value). applyToAll не знает, какое будет изменение; это решает тот, кто вызывает. Второй вызов даже не даёт своей функции имени. Он пишет функцию прямо в скобках вызова. Функция без имени называется анонимной функцией. Она удобна для коротких функций, которые нужны только в одном месте, и короткую можно уместить в одну строку.
Когда вы передаёте функцию, пишите её без скобок: double, а не double(5). Со скобками вы вызываете её сразу и передаёте её результат, число 10:
local function applyToAll(list, change)
local result = {}
for _, value in ipairs(list) do
table.insert(result, change(value))
end
return result
end
local function double(n)
return n * 2
end
local prices = {2, 3, 5}
print(table.concat(applyToAll(prices, double(5)), " "))Программа завершается с ошибкой:
main.lua:4: attempt to call a number value (local 'change')applyToAll получила в change число 10 и попыталась его вызвать. Функции, переданные другим функциям, вы будете встречать часто: в следующем упражнении вы передадите одну из них в table.sort.
Задание
- 1
По субботам все цены на прилавке Эммы выше на 2 монеты. Напишите функцию
saturdayPriceс параметромprice, которая возвращаетprice + 2. Затем передайте её вapplyToAllвместе сpricesи выведите результат, соединённый с помощьюtable.concat(…, " "). Программа выводит7 10 22 14 5. - 2
В конце дня Эмма продаёт всё за полцены. Выведите цены, разделённые на 2 с помощью
//, но на этот раз без именованной функции: напишите анонимную функцию прямо в вызовеapplyToAll. Программа выводит2 4 10 6 1. - 3
Теперь напишите функцию, которая принимает функцию: локальную функцию
countIfс двумя параметрами,listиcheck. Она возвращает, для скольких элементовlistфункцияcheckвозвращаетtrue. - 4
Используйте
countIfс анонимными функциями, чтобы узнать, сколько цен выше 7 монет и сколько ниже 5 монет. Программа выводит:Цен больше 7: 3 Цен меньше 5: 1