Question

For some reason, I'm having issues wrapping my head around the appropriate way to use parameters in a function, and later call for that function and return the correct parameters. If I wanted to use a function to find out the type of shape used. This shape contains data right after the shape abbreviation, such as Sq105428, that I would like to use. Quick Ex:

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

Later, I would call for the variables returned and use them. I'm having problems understanding how to properly call for those variables that were returned. In my code, I would like to take the three variables and use them throughout the code. How would I properly call for them?

I understand that:

function f() body end  ==  f = function() body end -- pg 15 PIL and helps me to understand

I also understand how to properly use mathematical functions such as:

function exp (x)
    print x^2
end

print exp(4) -- yields 16

But what is the appropriate way to call for my example if I want to use the three variables at different points of the code? I'm having problems completely understanding how to properly construct the function call and call for that later. Is it as easy as:

Example = math.floor(math.pi * Shape(Shape_side) + 0.5) -- is this ok?

I appreciate the help.

Was it helpful?

Solution

That's not exactly right. First, you're setting global variables within your function, but if they are just temporaries used for your function, you should definitely use locals.

Now back to your function:

function(...)

means that you want to receive variable number of arguments in your function without assigning tchem to any variable yet. To use these arguments, you need to assign them to named variables, like this:

local side, type, data = ...

or use select function.

What you really want (I guess from your call to math.floor) is just tell the function, which data is should return. To do that, you don't need multiple arguments, you just need one argument:

function shape(what)

Then based on what's in what, return only that data, or (for example), if what is not provided, return all the data needed:

if what == "side" then
    return side
elseif what == "whatever" then
    return whatever
elseif not what then
    return side, whateveer
else
    return nil
end

Of course that's just an example. To use multiple return values, you need to store them somewhere:

local side, whatever = shape() -- returns multiple values, because `what` is nil
local result = math.floor(math.pi * side + 0.5)

About efficiency of your function:

It looks like it's suboptimal at best. Each time you call the function, it's parsing the input provided. So if you want to get data, it has to go over the input, if you want to get shape's side, it has to go over the input again. Each time you call the function, you're redeclaring a global Shapes.

It's also best if functions don't operate on global variables at all (apart from calling some other global functions, for example). It makes them more universal (for instance parse input from provided variables, not from a global input).

I might be misunderstanding your function's purpose, but I would go about it a bit differntly:

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

Now you would store all the data you need and simply later use it without having to reinvoke the function and parse the input again:

local type, data, side = Shape(userInput)

Or better yet, have the function return a table and access the data in a nicer way:

...
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
...

and then store the data as:

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)

Now this is slower than multiple local values, but it's cleaner, imo, which is important, if you're new to Lua. There are some other things that could make the function better, faster (like requiring input to start with shape type), but I won't bore you with that.

So back to your original question, to use multiple return values, you need to store them in variables. If your function returns multiple values, but you only make assignment to one variable, the rest of the data is discarded:

local type = Shape(input) --assuming the function returns multiple values, not a table
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top