Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lua - How can I grab any return?

Tags:

lua

I am interested in grabbing any return format of a function. For example

function foo()
  return 1
end

local result = foo() -- foo is numeric 1

function foo()
  return {1,2,3}
end
local result1, result2, result3 = foo()
local result = foo() -- this is bad as result is `1` but `2` and `3` are lost

function foo()
  return 1, 2, 3
end
local result = foo() -- foo is a table with all the numbers, that's ok

I am building a profiler which will overwrite functions with proxy functions but I need to know the data returned, then check type() of it and access accordingly` but from the code it can be seen that I am unable to access all 3 situations with one method. Is there any ?

like image 286
lukas.pukenis Avatar asked Jan 22 '16 15:01

lukas.pukenis


People also ask

How do I return in Lua?

The Lua return keyword is a built in keyword in the Lua programming, which is used to return the result from a function. There is an implicit return at the end of the Lua functions. As per syntactic reason the return statement should be the last statement of a block or function, before the end keyword.

What does the hashtag do in Lua?

# is the length operator in Lua. It returns the count of how many objects there are in an array. In this case, it returns the number of how many children in an instance there are.


3 Answers

If the maximum number of returns is known, use something like

v1,v2,v3 = foo()

but you won't be able to tell whether foo returned two values or three, with the last one being nil.

The robust solution is to collect all returns in a table:

v = table.pack(foo())

Then v.n contains the number of returned values, including all nils.

like image 76
lhf Avatar answered Oct 27 '22 18:10

lhf


Here's a version that works on any Lua version 5.1+.

local function WrapAndInspect(Inspector, FunctionToCall)
    local function Inspect(...)
        Inspector(...)
        return ...
    end
    local function Wrapper(...)
        return Inspect(FunctionToCall(...))
    end
    return Wrapper
end

What WrapAndInspect does is generate a function that will call the given function, then pass its return values to a second function you provide. That function can do whatever processing you feel is necessary on them. But the framework will ensure that the return values from the original function are passed as they were.

Here's a variation that does something similar, but instead of wrapping the FunctionToCall, it returns a function that takes a function to be called (along with its parameters):

local function CallAndInspect(Inspector)
    local function Inspect(...)
        Inspector(...)
        return ...
    end
    local function Caller(FunctionToCall, ...)
        return Inspect(FunctionToCall(...))
    end
    return Caller
end

You could use this one on any particular function you want to inspect.

like image 23
Nicol Bolas Avatar answered Oct 27 '22 17:10

Nicol Bolas


Here is a workaround for those that do not have access to table.pack. To me it seems simple and it should work on lua 5.1 and above - and maybe even earlier lua versions.

table_pack should work like table.pack

function table_pack(...)
    return {n=select("#", ...), ...}
end
function foo()
    return 1, 2, 3
end

local v = table_pack(foo())
print(v.n)
like image 44
Rochet2 Avatar answered Oct 27 '22 19:10

Rochet2