[Variables] Funzione / ambito variabile (passa per valore o riferimento?)


Answers

I tipi di function , table , userdata e thread (coroutine) di Lua vengono passati per riferimento. Gli altri tipi vengono passati per valore. O come piace a qualcuno di metterlo; tutti i tipi vengono passati per valore, ma function , table , userdata e thread sono tipi di riferimento.

string è anche una sorta di tipo di riferimento, ma è immutabile, internato e copy-on-write - si comporta come un tipo di valore, ma con prestazioni migliori.

Ecco cosa sta succedendo:

local a = 9
local t = {4,6}

function moda(a)
  a = 10 -- sets 'a', which is a local introduced in the parameter list
end

function modt(t)
  t[1] = 7 -- modifies the table referred to by the local 't' introduced in the parameter list
  t[2] = 8
end

Forse questo metterà le cose in prospettiva sul perché le cose sono come sono:

local a = 9
local t = {4,6}

function moda()
  a = 10 -- modifies the upvalue 'a'
end

function modt()
  t[1] = 7 -- modifies the table referred to by the upvalue 't'
  t[2] = 8
end

-- 'moda' and 'modt' are closures already containing 'a' and 't',
-- so we don't have to pass any parameters to modify those variables
moda()
modt()
print(a)  -- now print 10
print(t[1]..t[2])  -- still print 78
Question

Sono completamente confuso dall'oscillazione della variabile di Lua e dall'argomento della funzione passando (valore o riferimento).

Guarda il codice qui sotto:

local a = 9        -- since it's define local, should not have func scope
local t = {4,6}    -- since it's define local, should not have func scope

function moda(a)
  a = 10           -- creates a global var?
end
function modt(t)
  t[1] = 7         -- create a global var?
  t[2] = 8
end

moda(a)
modt(t)
print(a)  -- print 9 (function does not modify the parent variable)
print(t[1]..t[2])  -- print 78 (some how modt is modifying the parent t var) 

In quanto tale, questo comportamento mi confonde completamente.

  • Questo significa che le variabili di tabella vengono passate alla funzione per riferimento e non per valore?

  • In che modo la creazione della variabile globale è in conflitto con la variabile locale già definita?

    • Perché modt è in grado di modificare la tabella ma moda non è in grado di modificare una variabile?



Non ripeterò ciò che è già stato detto su Bas Bossink e le risposte di jA_cOp sui tipi di riferimento, ma:

- dal momento che è definito locale, non dovrebbe avere scope di funzionalità

Questo non è corretto Le variabili in Lua sono in senso lessicale , il che significa che sono definite in un blocco di codice e in tutti i suoi blocchi nidificati.
Ciò che è local è creare una nuova variabile che è limitata al blocco in cui si trova l'istruzione, un blocco che è il corpo di una funzione, un "livello di rientro" o un file.

Ciò significa che ogni volta che si fa riferimento a una variabile, Lua eseguirà una "scansione verso l'alto" fino a quando non troverà un blocco di codice in cui tale variabile è dichiarata locale, in modo predefinito all'ambito globale se non esiste tale dichiarazione.

In questo caso, a e t sono dichiarati locali ma la dichiarazione è in ambito globale, quindi a e t sono globali; o al massimo, sono locali al file corrente.

Non vengono quindi riprogrammate local all'interno delle funzioni, ma vengono dichiarate come parametri, che ha lo stesso effetto. Se non fossero stati parametri di funzione, qualsiasi riferimento all'interno dei corpi delle funzioni si riferirebbe comunque alle variabili esterne.

C'è un tutorial su Scope su lua-users.org con alcuni esempi che potrebbero aiutarti più del mio tentativo di spiegazione. Anche la programmazione nella sezione di Lua sull'argomento è una buona lettura.