2016-01-22 3 views
5

Меня интересует захват любого формата возврата функции. НапримерLua - Как я могу получить возврат?

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 

Я строю профайлер, который перепишет функции с прокси-функциями, но мне нужно знать, что данные возвращаемые, а затем проверить type() его и accordingly` доступа, но из кода можно видеть, что я не удалось получить доступ ко всем 3 ситуациям одним способом. Есть ли ?

+0

@NicolBolas, как я дал три примера 'Foo()' функции должно быть ясно, что я хочу, чтобы захватить все три случая 'Foo'. Пожалуйста, никаких тангенсов здесь не требуется. –

+0

@NicolBolas спасибо за помощь :) Я обновил свой вопрос, надеюсь, теперь его станет более ясно –

+0

Итак, вы являетесь фактическим абонентом функции. Вы собираетесь проверить эти результаты, а затем вернуть их, как если бы вы были «foo»? –

ответ

8

Если максимальное количество возвратов известно, использовать что-то вроде

v1,v2,v3 = foo() 

, но вы не будете в состоянии сказать, вернулись ли foo два значения или три, с последним будучи нолем.

Надежное решение собрать все возвращается в таблице:

v = table.pack(foo()) 

Затем v.n содержит количество возвращаемых значений, в том числе всех Nils.

+4

Обратите внимание, что table.pack требует Lua 5.2+ –

+4

Поскольку Lua 5.2 был выпущен 4 года назад, это должно быть нормально, если вы не используете LuaJIT, который поддерживает только Lua 5.1. – lhf

+0

Это то, что я хотел! Благодаря! –

4

Вот версия, которая работает с любой версией Lua 5.1+.

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

Что WrapAndInspect делает генерировать функцию, которая будет вызывать данную функцию, а затем передать его возвращаемые значения для второй функции вы предоставляете. Эта функция может делать любую обработку, которую вы считаете необходимой для них. Но структура гарантирует, что возвращаемые значения из исходной функции передаются так, как они были.

Вот вариант, который делает что-то подобное, но вместо того, чтобы оборачивать FunctionToCall, она возвращает функцию, которая принимает функцию, которая будет вызвана (наряду с его параметрами):

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

Вы могли бы использовать этот один на любую конкретную функцию, которую вы хотите проверить.

3

Это временное решение для тех, у кого нет доступа к table.pack. Мне кажется, что это просто, и он должен работать на lua 5.1 и выше - и, возможно, даже на ранних версиях lua.

table_pack должен работать как table.pack

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

local v = table_pack(foo()) 
print(v.n) 
+1

'...' должен быть последним для расширения до всех аргументов, поэтому '{n = select (" # ", ...), ...}' работает лучше! – siffiejoe

+0

@siffiejoe Интересно, есть ли какая-то реальная разница. Я проверил этот код на lua 5.3. Есть ли случай, когда он на самом деле «работает лучше» - как вы говорите? – Rochet2

+2

Там * есть * реальная разница: ваш код работает только для одного аргумента. Вы можете проверить, добавив 'for i = 1, v.n do print (i, v [i]) end' в ваш примерный код выше. [Quote] (http://www.lua.org/manual/5.3/manual.html#3.4.9) из руководства Lua: если последнее поле в списке имеет форму exp, а выражение - вызов функции или выражение vararg, то все значения, возвращаемые этим выражением, последовательно входят в список (см. п. 3.4.10). '...' не является последним выражением в конструкторе таблицы, поэтому оно настраивается на одно значение. – siffiejoe

Смежные вопросы