Il giorno 03 Luglio 2009 12.45, Giovanni
Messina[email protected] ha scritto:
sorgono quindi le domande
- questa impostazione vale anche in altri casi?
metterla in termini di passaggio per valore o per riferimento rischia
più che altro di confondere le idee; la questione è molto più
semplice: bisogna vedere cosa stai facendo: creando un oggetto nuovo o
modificando un oggetto.
esempio concreto:
a = “ciao”
b = a
a = a.upcase
a => “CIAO”
b => “ciao”
qui non modifichi a, ma lo riassegni.
invece:
a = “ciao”
b = a
a.upcase!
a => “CIAO”
b => “CIAO”
ogni volta che fai questo = quello stai solo creando un riferimento;
ogni volta che fai
questo.metodo_che_modifica_questo_invece_di_creare_un_nuovo_oggetto(),
modifichi l’oggetto, che quindi sarà diverso da qualunque riferimento
si parta per arrivarci.
altro esempio (un errore che commettevo spessissimo anche in python):
a = [[1]] * 5
a => [[1], [1], [1], [1], [1]]
b = a
b => [[1], [1], [1], [1], [1]]
a[0] << 3
a => [[1, 3], [1, 3], [1, 3], [1, 3], [1, 3]]
b => [[1, 3], [1, 3], [1, 3], [1, 3], [1, 3]]
nota che non solo ho modificato b modificando a, ma ogni elemento di a
(o di b) è stato modificato.
questo perché << è un metodo che modifica l’oggetto.
per eliminare ogni dubbio c’è il metodo object_id. ad esempio,
nell’irb che ho aperto in questo momento:
a.object_id => 30095320
b.object_id => 30095320
ma, soprattutto:
a.collect {|x| x.object_id} => [30095330, 30095330, 30095330,
30095330, 30095330]
ovvero, a è un oggetto di tipo array che contiene 5 elementi, i quali
sono 5 riferimenti allo stesso oggetto, cioè [1, 3].
- come effettuare invece un passaggio per valore, senza dover fare
list[0].length.times{|i| a[i]=list[0][i]}
sui singoli oggetti puoi usare clone o dup (credo siano alias); però
dup bara, duplica l’oggetto esterno ma non quelli interni:
a = [[1], [1], [1], [1], [1]]
b = a
c = a.dup
a << 2
a => [[1], [1], [1], [1], [1], 2]
b => [[1, 2], [1], [1], [1], [1], 2]
c => [[1], [1], [1], [1], [1]]
però:a[0] << 3
a => [[1, 3], [1], [1], [1], [1], 2]
b => [[1, 3], [1], [1], [1], [1], 2]
c => [[1, 3], [1], [1], [1], [1]]
non so se esiste un metodo già definito per fare la “copia profonda”
di un oggetto; se non esiste, devi farlo tu a mano.
pietro