2012-01-06 14 views
6

Ho una funzione lua che accetta più parametri e restituisce tanti valori quanti sono i parametri. Ogni valore di ritorno corrisponde a un parametro. Per illustrare, si consideri una funzione che legge il valore di una coppia chiave/valore da un database:Best practice per la restituzione di un errore da una funzione lua che restituisce più valori

val1, val2, val3 = my_function("key1", "key2", "key3"); 
val1 = my_function("key1"); 

Qual è il modo migliore per restituire un errore da my_function? (ad esempio se una "chiave" fornita non è valida)

Capisco un modo è quello di restituire due valori su errore, nil e una stringa di errore. È questo l'approccio migliore? Per esempio:

val1, val2, val3 = my_function("key1", "key2", "key3"); 
if val1 then 
    -- Use val1, val2, and val3. 
else 
    print("ERROR: " .. val2); 
end 

Modifica

Alcuni punti aggiuntivi:

  1. Lo script Lua è essere eseguito da un programma C utilizzando lua_pcall().
  2. Il programma C non deve interrompersi se lo script non riesce.
  3. my_function() è implementato in C.
  4. Quando my_function() non riesce, dovrebbe anche restituire un codice di errore (o un messaggio) che indica il motivo per cui non è riuscito.

risposta

6

Il metodo standard di gettare errori in Lua è tramite la funzione di errore (manual, api) o tramite assert (che utilizza internamente error comunque).

Poiché la tua funzione è in C, dovresti chiamare lua_error al suo interno, per ottenere lo stesso effetto.

Ma tieni presente che la tua funzione ora è "insicura". Se non modificato, il seguente codice farà l'equivalente di "un'eccezione" e quindi arrestare il programma, se chiave1, chiave2 o key3 sono "erronea":

val1, val2, val3 = my_function("key1", "key2", "key3") 

A volte è ok per lasciare che il programma "semplicemente in crash "se gli input sono sbagliati. A seconda della configurazione, l'utente riceverà un messaggio con l'ultimo errore e una traccia di stack o qualcosa del genere.

Se "lasciando che il crash del programma" non è un'opzione, si può fare l'equivalente di che lo circonda con un blocco "try-catch" utilizzando la funzione pcall, e l'aggiunta di una nuova variabile chiamata ok:

ok, val1, val2, val3 = pcall(my_function, "key1", "key2", "key3") 
if ok then 
    -- Use val1, val2, and val3. 
else 
    print("ERROR: " .. val1) -- notice that we use val1 here, not val2 
end 

Si noti che non è necessario inserire pcall esattamente sopra my_function. Come per le eccezioni, il recupero degli errori può avvenire più in alto nella catena di chiamate: nella funzione che chiama my_function, o nella funzione che chiama quella, ecc.Ad esempio, se si chiama my_function da una funzione chiamata parent, e genitore da uno chiamato grandParent, si può fare questo:

-- parent is "insecure" since my_function is "unprotected" 
function parent(key1, key2) 
    local val1, val2, val3 = my_function(key1, key2, "key3") 
    return val1, val2, val3 
end 

-- grandParent calls parent in a "safe" way 
function grandParent() 
    local ok, val1, val2, val3 = pcall(parent, "key1", "key2") 
    if ok then 
    -- Use val1, val2, and val3. 
    else 
    print("ERROR: " .. val1) 
    end 
end 
+0

Ho modificato la domanda per chiarire alcuni punti. Poiché lo script lua (che alla fine chiama 'my_function()') viene eseguito da C con 'lua_pcall()', dovrei 'my_function()' restituire una variabile "ok" come descritto sopra? (ad esempio, ok, val1, val2, val3 = my_function() '). – Ben

+0

@Ben, sì, includerei un valore 'ok' aggiuntivo - che sembra essere il modo più pulito. Vorrei anche raccomandare una revisione nel design; poiché entrambe le funzioni sono in C, probabilmente sarà più semplice (e più veloce) dimenticare Lua e fare semplicemente tutto in C. – kikito

+0

@kikto, grazie per aver chiarito. In questo caso ha sicuramente senso usare lua (o un equivalente) per estendere il prodotto. – Ben

0

La pratica abituale è di gettare gli errori quando il programma non è in grado di recuperare (handle di file male per esempio) e segnalare gli errori quando è possibile ripristinare (file non trovato per esempio). Nel tuo caso, penso che semplicemente restituire nil per le chiavi non valide sia il modo migliore.

+0

Se voglio che my_function() restituisca anche il motivo per cui ha fallito, stai sostenendo che se 'val1, val2, val3 = my_function()' fallisce, 'val1' dovrebbe essere' nil' e 'val2' dovrebbe essere il codice di errore /Messaggio? – Ben

+0

@ Ben, ho pensato che l'unica ragione fosse "chiave non valida". – lhf

Problemi correlati