Definire i valori predefiniti per gli argomenti della funzione


86

Nel wiki di Lua ho trovato un modo per definire i valori predefiniti per gli argomenti mancanti:

function myfunction(a,b,c)
    b = b or 7
    c = c or 5
    print (a,b,c)
end

Quello è l'unico modo? Lo stile PHP myfunction (a,b=7,c=5)non sembra funzionare. Non che il metodo Lua non funzioni, mi chiedo solo se questo sia l'unico modo per farlo.

Risposte:


87

Se vuoi argomenti con nome e valori predefiniti come PHP o Python, puoi chiamare la tua funzione con un costruttore di tabelle:

myfunction{a,b=3,c=2}

(Questo è visto in molti posti in Lua, come le forme avanzate dei moduli di protocollo e dei costruttori di LuaSocket in IUPLua .)

La funzione stessa potrebbe avere una firma come questa:

function myfunction(t)
    setmetatable(t,{__index={b=7, c=5}})
    local a, b, c =
      t[1] or t.a, 
      t[2] or t.b,
      t[3] or t.c
    -- function continues down here...
end

Eventuali valori mancanti dalla tabella dei parametri saranno presi dalla __indextabella nella sua metatables (vedere la documentazione sui metatables ).

Naturalmente, sono possibili stili di parametri più avanzati utilizzando costruttori di tabelle e funzioni: puoi scrivere tutto ciò di cui hai bisogno. Ad esempio, ecco una funzione che costruisce una funzione che prende tabelle di argomenti denominati o posizionali da una tabella che definisce i nomi dei parametri ei valori predefiniti e una funzione che accetta un elenco di argomenti regolari.

Come funzionalità non a livello di linguaggio, tali chiamate possono essere modificate per fornire nuovi comportamenti e semantiche:

  • È possibile fare in modo che le variabili accettino più di un nome
  • Le variabili di posizione e le variabili di parole chiave possono essere inframmezzate e la definizione di entrambe può dare la precedenza a entrambe (o causare un errore)
  • È possibile creare variabili senza posizione solo per parole chiave, nonché variabili senza posizione senza nome
  • La costruzione della tabella abbastanza dettagliata potrebbe essere eseguita analizzando una stringa
  • L'elenco degli argomenti potrebbe essere utilizzato letteralmente se la funzione viene chiamata con qualcosa di diverso da 1 tabella

Alcune funzioni utili per scrivere i traduttori di argomenti sono unpack(passando a table.unpackin 5.2), setfenv(deprecato in 5.2 con la nuova _ENVcostruzione) e select(che restituisce un singolo valore da un dato elenco di argomenti, o la lunghezza dell'elenco con '#').


AI ho appena iniziato a usare lua Lo terrò semplice per il momento ma il tuo post è molto informativo. Potrebbe tornare utile in seguito. Grazie.
ripat

1
Nella maggior parte dei casi, mantenerlo semplice è la strada da percorrere. Le interfacce meta-parametro sono realmente necessarie solo per oggetti con un numero elevato di attributi opzionali (come gli oggetti dell'interfaccia utente).
Stuart P. Bentley

Penso che questa risposta sia quella che risolve le domande, non quella attualmente contrassegnata come accettata. Grazie per l'illuminazione :)
Annulla

2
Va notato che l' x or defaultespressione utilizzata anche in questa risposta non è realmente un vero equivalente ai valori predefiniti dei parametri, ma solo una soluzione alternativa semplicistica che funziona solo se entrambi nile falsesono valori di parametro non validi. Diciamo che il valore predefinito per un parametro booleano xè truee il chiamante passa un esplicito false. Poi x or truetrue, anche se è falsestato esplicitamente approvato. Sarebbe una versione migliore if x == nil then x = default end, che è anche più leggibile; tuttavia non è ancora in grado di gestire nilargomenti espliciti .
Jesper

Oh, ehi, questa è la risposta accettata ora! Bello. (Per la cronaca, e per contestualizzare il commento di @ Undo, la risposta di jpjacobs di seguito è stata la risposta accettata per molto tempo: ho quasi ricevuto un secondo badge populista .)
Stuart

46

Secondo me non c'è un altro modo. Questa è solo la mentalità Lua: niente fronzoli e, a parte un po 'di zucchero sintattico, nessun modo ridondante di fare cose semplici.


10
Questa risposta è completamente smentita dalla risposta di Stuart P. Bentley di seguito, in cui la funzione viene chiamata con un costruttore di tabelle. Questo è uno dei punti di forza di Lua: sebbene non abbia un mucchio di fronzoli, i mattoni fondamentali di Lua ti consentono di fare cose senza limiti, davvero notevoli per le dimensioni ridotte e la semplicità del linguaggio.
Colin D Bennett

@ColinDBennett Grazie per aver parlato: sembrerebbe che l'OP abbia letto il tuo commento e, a dicembre, ha cambiato di conseguenza la risposta accettata. (E ora è "la risposta di Stuart P. Bentley sopra", per chiarezza: occhiolino :)
Stuart P. Bentley

21

Tecnicamente, c'è b = b == nil and 7 or b(che dovrebbe essere usato nel caso in cui falsesia un valore valido come valore false or 77), ma probabilmente non è quello che stai cercando.


1
Se non stai cercando false, un modo più semplice è mettere la variabile per prima e quella predefinita per ultima. b = b or 7
Rebs

2
Poiché l'OP lo ha menzionato nella loro domanda, ho pensato che sarebbe stato superfluo menzionarlo (la domanda riguardava i modi per definire variabili predefinite diverse da b = b or 7 ).
Stuart P. Bentley

6

L'unico modo che ho trovato finora che abbia senso è fare qualcosa del genere:

function new(params)
  params = params or {}
  options = {
    name = "Object name"
  }

  for k,v in pairs(params) do options[k] = v end

  some_var = options.name
end

new({ name = "test" })
new()
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.