Продолжу рассказывать про знаки препинания. В этом посте — 3 разных истории про пару круглых скобок.
1. Вызовы функций
Если функция вызывается с одним аргументом — строковым или табличным литералом, то скобочки необязательны.
local function identity(x)
return x
end
print(identity "test" == "test")
print(table.unpack(identity {"test"}) == "test")
Это чисто синтаксическая фишка, которая никак не влияет на исполнение кода. Очень удобно, чтобы вызвать функцию и передать ей таблицу с опциями.
local logger = getLogger {
name = "main",
level = "info",
output = {stdout},
}
Если несколько литералов так разместить подряд, получится ряд последовательных вызовов:
myFunc "hello" "world" {"how do you do"}
-- myFunc("hello")("world")({"how do you do"})
Используя эту фичу, можно воплотить всякие норкоманские вещи. Как вам вот такой форматтер с интерполяцией?
local myVar = 42
print(format "myVar = " {myVar} ", and I'm running " {_VERSION} ())
--> myVar = 42, and I'm running Lua 5.3
2. Ещё про литералы
У всех строк есть метатаблица, у которой __index = string. Это значит, что можно вместо string.gsub(str, ...) писать str.gsub(str, ...), или str:gsub(...). Очень удобно, особенно последнее.
Но вот просто так заменить str литералом нельзя. "test":gsub(...) — синтаксически неправильный код. Выручат скобки вокруг литерала: ("test"):gsub(...). Постоянно этим пользуюсь.
Та же ситуация, если мы хотим проиндексировать табличный литерал: {foo = "bar"}.foo выдаст ошибку. Лечится аналогично: ({foo = "bar}).foo.
Кроме индексации, скобочки нужны при вызове: вместо function() return 42 end() нужно писать (function() return 42 end)().
Наконец, есть ещё литералы численные: 42, например. В обычной Lua оборачивать их в скобки смысла, пожалуй, и не имеет, но с небольшим шаманством опять потребуются скобочки:
debug.setmetatable(0, {__call = function(self) print(self) end});
(42)()
--> 42
Правда, в OpenComputers отключён debug.setmetatable.
3. Функции с множественным выхлопом
В Lua функция может вернуть несколько значений:
local function test()
return 1, 2, 3
end
print(test())
--> 1 2 3
Однако бывает, что нужно достать только одно значение, а про остальные забыть. Для этого нужно обернуть в скобки вызов функции, вот так:
print((test()))
--> 1
Скобочки возьмут только первое значение и отбросят остальные. С помощью функции select можно выбрать и другое по счёту:
local function identity(...)
return ...
end
print((select(3, identity(10, 9, 8, 7, 6, 5, 4, 3, 2, 1))))
--> 8