2016-01-22 14 views
5

Sono interessato ad acquisire qualsiasi formato di ritorno di una funzione. Per esempioLua - Come posso ottenere un ritorno?

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 

Sto costruendo un profiler che sovrascriverà funzioni con le funzioni di proxy, ma ho bisogno di sapere i dati restituiti, quindi controllare type() di esso e l'accesso accordingly` ma dal codice si può vedere che io sono impossibile accedere a tutte e 3 le situazioni con un solo metodo. C'è qualche ?

+0

@NicolBolas come io ho dato tre esempi di 'foo()' funzione dovrebbe essere chiaro che voglio prendere tutti e tre i casi di 'foo'. Per favore non sono necessarie tangenti qui. –

+0

@NicolBolas grazie per l'aiuto :) Ho aggiornato la mia domanda, spero sia più chiara ora –

+0

Quindi sei il vero chiamante della funzione. Hai intenzione di ispezionare quei risultati, quindi restituirli come se fossi "pippo"? –

risposta

8

Se si conosce il numero massimo dei rendimenti, usare qualcosa come

v1,v2,v3 = foo() 

, ma non sarà in grado di dire se foo restituito due valori o tre, con l'ultima delle quali a zero.

La soluzione robusta è quello di raccogliere tutti i ritorni in una tabella:

v = table.pack(foo()) 

Poi v.n contiene il numero di valori restituiti, tra cui tutti i nils.

+4

Si noti che table.pack richiede Lua 5.2+ –

+4

Poiché Lua 5.2 è stato rilasciato 4 anni fa, questo dovrebbe essere ok, a meno che non si usi LuaJIT, che supporta solo Lua 5.1. – lhf

+0

Questo è quello che volevo! Grazie! –

4

Ecco una versione che funziona su qualsiasi Lua versione 5.1+.

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

Cosa WrapAndInspect fa è generare una funzione che chiamerà la funzione data, quindi passare i suoi valori di ritorno per una seconda funzione che fornisci. Quella funzione può fare qualunque elaborazione tu ritenga necessaria su di loro. Ma il framework garantirà che i valori di ritorno dalla funzione originale siano passati come erano.

Ecco una variante che fa qualcosa di simile, ma invece di avvolgere la FunctionToCall, restituisce una funzione che prende una funzione per essere chiamato (insieme con i suoi parametri):

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

si potrebbe usare questo uno su qualsiasi funzione particolare che si desidera esaminare.

3

Ecco una soluzione alternativa per coloro che non hanno accesso a table.pack. Per me sembra semplice e dovrebbe funzionare su lua 5.1 e versioni successive - e forse anche prima in lua.

table_pack dovrebbe funzionare come 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

Il '...' deve venire per ultimo per essere esteso a tutti gli argomenti, quindi '{n = select (" # ", ...), ...}' funziona meglio! – siffiejoe

+0

@siffiejoe Mi chiedo se ci sia una vera differenza. Ho provato questo codice su lua 5.3. C'è qualche caso in cui effettivamente "funziona meglio" - come dici tu? – Rochet2

+2

Là * è * una vera differenza: il tuo codice funziona solo per un argomento. Puoi controllare aggiungendo 'per i = 1, v.n do print (i, v [i]) end' al tuo codice di esempio sopra. Per [citazione] (http://www.lua.org/manual/5.3/manual.html#3.4.9) dal manuale di Lua: Se l'ultimo campo della lista ha il formato exp e l'espressione è una chiamata di funzione o un'espressione vararg, quindi tutti i valori restituiti da questa espressione entrano nella lista consecutivamente (vedere §3.4.10). '...' non è l'ultima espressione nel costruttore di tabelle, quindi è regolata su un valore. – siffiejoe

Problemi correlati