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
Другие вопросы по тегам