2012-11-16 7 views
6

Qual è lo scopo di passare argomenti a lua_resume e lua_yield?Lua: scopi argomento lua_resume e lua_yield

Capisco che alla prima chiamata a lua_resume gli argomenti vengono passati alla funzione lua che viene ripresa. Questo ha senso. Tuttavia, mi aspetto che tutte le chiamate successive a lua_resume "aggiornino" gli argomenti nella funzione della coroutine. Tuttavia non è questo il caso.

Qual è lo scopo del passaggio di argomenti a lua_resume per lua_yield da restituire? Può la funzione lua che gira sotto la coroutine avere accesso agli argomenti passati da lua_resume?

risposta

10

Ciò che Nicol ha detto. È ancora possibile conservare i valori del primo resume chiamata se si desidera:

do 
    local firstcall 
    function willyield(a) 
    firstcall = a 
    while a do 
     print(a, firstcall) 
     a = coroutine.yield() 
    end 
    end 
end 

local coro = coroutine.create(willyield) 
coroutine.resume(coro, 1) 
coroutine.resume(coro, 10) 
coroutine.resume(coro, 100) 
coroutine.resume(coro) 

stamperà

1 1 
10 1 
100 1 
+0

Mi sembra che questo non risponda alla domanda.L'OP riguardava l'API/c/funzioni lua_resume() e lua_yield(), che hanno una semantica diversa dalla libreria standard 'coroutine.resume()', ecc. (Ad esempio, lua_resume accetta tre argomenti - due sono lua_State ...) – BadZen

+0

Penso che risponda alla domanda sullo scopo del passaggio dei parametri e fornisce un esempio che è facile provare con un interprete Lua. Infatti, OP ha detto tanto nel suo commento sotto la risposta di Nicol. Puoi sempre fornire la tua risposta se pensi di averne una migliore. –

+0

C'è una grande differenza tra l'oggetto coroutine in libs (che ad esempio incapsula un lua_State) e utilizza l'API C. Non ho una risposta migliore, quindi ho aperto un'altra domanda chiedendo in particolare l'API C. La risposta di Nichol e la tua qui parlano entrambi dell'oggetto della biblioteca di coroutine. Ci sono circa 100 linee di codice che la implementano in termini di API lua_ *. Non è ovvio e la documentazione è breve nei dettagli. – BadZen

5

Lua non può dare magicamente agli argomenti originali nuovi valori. Potrebbero non essere più in pila, a seconda delle ottimizzazioni. Inoltre, non vi è alcuna indicazione su dove si trovava il codice quando è stato rilasciato, quindi potrebbe non essere più in grado di vedere quegli argomenti. Ad esempio, se la coroutine ha chiamato una funzione, quella nuova funzione non può vedere gli argomenti passati in quello vecchio.

coroutine.yield() restituisce gli argomenti passati alla chiamata resume che continua la coroutine, in modo che il sito della chiamata di rendimento possa gestire i parametri così come desidera. Permette al codice di riprendere a comunicare con il codice specifico facendo il rendimento. yield() passa i suoi argomenti come valori di ritorno da resume e resume passa i suoi argomenti come valori di ritorno a yield. Questo crea un percorso di comunicazione.

Non è possibile farlo in altro modo. Certamente non modificando argomenti che potrebbero non essere visibili dal sito yield. È semplice, elegante e ha un senso.

Inoltre, è considerato estremamente scortese andare a colpire i valori di qualcuno. Soprattutto una funzione già in funzione. Ricorda: gli argomenti sono solo variabili locali piene di valori. L'utente non dovrebbe aspettarsi che il contenuto di quelle variabili cambi, a meno che non cambi le stesse. Sono variabili, dopotutto. Possono essere modificati solo localmente; da qui il nome.

+0

Grazie! Quindi per chiarire, una volta avviata una coroutine, i valori locali non possono essere modificati esternamente? Suppongo che avrei bisogno di comunicare agli interni della coroutine con variabili globali allora? Ad esempio, potrei avere un conteggio di "oggetti vicini" in un gioco, in cui la coroutine deve sapere quanti altri oggetti si trovano a una distanza. Per fare questo dovrei avere un globale per memorizzare il numero di oggetti vicini? Speravo di poter valutare la coroutine direttamente prima di riprendere per evitare di abbattere lo spazio dei nomi con i globali. – RandyGaul

+0

I valori possono essere modificati; devi solo assegnare il risultato della chiamata a coroutine.yield() alla stessa variabile che hai passato come parametro in origine. Guarda la mia risposta per esempio. –

+0

@RandyGaul: "* una volta avviata una coroutine, i valori locali non possono essere modificati esternamente *" Le variabili 'local' non possono essere modificate esternamente * periodo *; le coroutine non sono speciali. Se si desidera passare questo numero, passarli come parametri per 'riprendere' e collezionarli come valore di ritorno da 'yield'. Come ho affermato, questa è l'interfaccia di comunicazione che hai. –