Lua: функции с множественным возвратом
По какой-то причине у меня возникают проблемы, когда я пытаюсь найти подходящий способ использования параметров в функции, а затем вызвать эту функцию и вернуть правильные параметры. Если бы я хотел использовать функцию, чтобы узнать тип используемой формы. Эта форма содержит данные сразу после аббревиатуры формы, такие как Sq105428, которые я хотел бы использовать. Быстрый пример:
function Shape(...) -- can I use "..." or should I put "Type, Shape_data, Shape_side" inside?
Shapes = {["Tri"] = 3, ["Sq"] = 4, ["Po"] = 5, ["Hex"] = 6}
for k,v in pairs (Shapes) do
Type = string.match(input, k..".*")
if Type == k then
Shape_data = string.match(input,Type.."(.*)")
Shape_side = v
end
end
return Type, Shape_data, Shape_side -- can I call for these later in my code?
end
Позже я бы вызвал возвращенные переменные и использовал их. У меня проблемы с пониманием, как правильно вызвать те переменные, которые были возвращены. В моем коде я хотел бы взять три переменные и использовать их по всему коду. Как бы я их правильно назвал?
Я это понимаю:
function f() body end == f = function() body end -- pg 15 PIL and helps me to understand
Я также понимаю, как правильно использовать математические функции, такие как:
function exp (x)
print x^2
end
print exp(4) -- yields 16
Но как правильно назвать мой пример, если я хочу использовать три переменные в разных точках кода? У меня проблемы с полным пониманием того, как правильно сконструировать вызов функции и вызвать ее позже. Это так же просто, как:
Example = math.floor(math.pi * Shape(Shape_side) + 0.5) -- is this ok?
Я ценю помощь.
1 ответ
Это не совсем верно. Во-первых, вы устанавливаете глобальные переменные внутри своей функции, но если они являются временными, используемыми для вашей функции, вам определенно следует использовать локальные переменные.
Теперь вернемся к вашей функции:
function(...)
означает, что вы хотите получить переменное число аргументов в вашей функции, еще не назначая tchem какой-либо переменной. Чтобы использовать эти аргументы, вам нужно назначить их именованным переменным, например так:
local side, type, data = ...
или используйте функцию выбора.
Что вы действительно хотите (я думаю, из вашего звонка math.floor
) просто скажите функции, какие данные должны возвращать. Для этого вам не нужно несколько аргументов, вам нужен только один аргумент:
function shape(what)
Затем на основе того, что в what
вернуть только эти данные или (например), если что не предоставлено, вернуть все необходимые данные:
if what == "side" then
return side
elseif what == "whatever" then
return whatever
elseif not what then
return side, whateveer
else
return nil
end
Конечно, это всего лишь пример. Чтобы использовать несколько возвращаемых значений, вам нужно их где-то хранить:
local side, whatever = shape() -- returns multiple values, because `what` is nil
local result = math.floor(math.pi * side + 0.5)
Об эффективности вашей функции:
Похоже, в лучшем случае это неоптимально. Каждый раз, когда вы вызываете функцию, она анализирует входные данные. Поэтому, если вы хотите получить данные, они должны пройти через input
, если вы хотите получить сторону фигуры, она должна пройти через input
снова. Каждый раз, когда вы вызываете функцию, вы переделываете глобальный Shapes
,
Также лучше, если функции вообще не работают с глобальными переменными (кроме вызова некоторых других глобальных функций, например). Это делает их более универсальными (например, анализирует входные данные из предоставленных переменных, а не из глобального ввода).
Я мог бы неправильно понять цель вашей функции, но я бы сделал это немного иначе:
local Shapes = {["Tri"] = 3, ["Sq"] = 4, ["Po"] = 5, ["Hex"] = 6} -- create a closure
function Shape(input)
for k, v in pairs(Shapes) do
local type = string.match(input, k) --I thinkg with your match you'd never get past the next line
if type then --no need to do the comparison, as type would be nil if no match is found
return k, string.match(input, k.."(.*)"), v
end
end
return nil --erroneous input, no match found
end
Теперь вы будете хранить все необходимые данные и просто позже использовать их без необходимости повторного вызова функции и повторного анализа ввода:
local type, data, side = Shape(userInput)
Или, что еще лучше, пусть функция вернет таблицу и получит более удобный доступ к данным:
...
if type then --no need to do the comparison, as type would be nil if no match is found
return {type = k, data = string.match(input, k.."(.*)"), side = v}
end
...
и затем сохранить данные как:
local userShape1 = Shape(userInput1)
local userShape2 = Shape(userInput2)
--now use the results
local result1 = math.floor(math.pi * userShape1.side + 0.5)
local result2 = math.floor(math.pi * userShape2.side + 0.5)
local dataResult1 = processShapeData(userShape1.data)
Теперь это медленнее, чем несколько локальных значений, но это чище, имо, что важно, если вы новичок в Lua. Есть некоторые другие вещи, которые могут сделать функцию лучше, быстрее (например, требовать ввода, чтобы начать с типа фигуры), но я не буду утомлять вас этим.
Итак, вернемся к исходному вопросу: чтобы использовать несколько возвращаемых значений, вам нужно хранить их в переменных. Если ваша функция возвращает несколько значений, но вы присваиваете только одну переменную, остальные данные отбрасываются:
local type = Shape(input) --assuming the function returns multiple values, not a table