2013-06-12 8 views
11

Sto imparando Ruby e ho appena trovato un comportamento interessante quando si utilizza il metodo Object#freeze con le variabili.Le variabili di congelamento in Ruby non funzionano

Dopo aver bloccato una variabile (sia Fixnum o Array), sono ancora in grado di modificarla! È strano, dal momento che per quanto mi riguarda questo non dovrebbe accadere e dovrebbe essere sollevato il numero TypeError.

Ecco il mio codice:

test = 666 
var = 90 
#ok 
var += 5 

puts "var.frozen? #{var.frozen?}"  
var.freeze  
puts "var.frozen? #{var.frozen?}" 

var = test 
puts "var = #{var}" 

Lo stesso vale per array:

test = [666] 
var = [90] 
#ok 
var += [5] 

puts "var.frozen? #{var.frozen?}"  
var.freeze  
puts "var.frozen? #{var.frozen?}" 

var = test 
puts "var = #{var}" 

Ma quando provo a spingere qualcosa nella matrice dopo il congelamento, si solleva un arror, come previsto:

test = [666] 
var = [90] 
#ok 
var += [5] 

puts "var.frozen? #{var.frozen?}"  
var.freeze  
puts "var.frozen? #{var.frozen?}" 

var << test 
puts "var = #{var}" 

Qualcuno può spiegarmi questo problema? Sembra strano.

Edit Sto usando Windows Xp + Rubino 1.9.3-P429

+1

curioso - perché 'test' =' 666': P – sircapsalot

+0

Questo non è ciò che fa il congelamento; funziona esattamente come previsto. Non è possibile congelare valori immutabili come numeri letterali e sicuramente non è possibile "congelare" le variabili in modo che non possano essere impostate su nuovi valori. Si bloccano solo oggetti. – meagar

+1

@meagar: è possibile bloccare i valori immutabili. È semplicemente inutile perché non possono essere comunque modificati. Ma '5.freeze' funziona ... nel senso che' 5.frozen? 'Restituisce' true'. –

risposta

32

È congelare oggetti, non variabili, cioè non è possibile aggiornare un oggetto ghiacciato, ma è possibile assegnare un nuovo oggetto alla stessa variabile . Considerate questo:

a = [1,2,3] 
a.freeze 
a << 4 
# RuntimeError: can't modify frozen Array 

# `b` and `a` references the same frozen object 
b = a 
b << 4  
# RuntimeError: can't modify frozen Array 

# You can replace the object referenced by `a` with an unfrozen one 
a = [4, 5, 6] 
a << 7 
# => [4, 5, 6, 7] 

Per inciso: è del tutto inutile per congelare Fixnum s, dal momento che sono oggetti immutabili.

+0

Beh, mi stai facendo trascurare riferendosi alle "variabili di congelamento", quello che avevo in mente era ovviamente il congelamento degli oggetti (la variabile è solo un'etichetta nel codice così non ha senso "congelarlo" :)) Ok, ora capisco come funziona questo congelamento, ma comunque, sono ancora un po 'confuso, perché l'assegnazione di un nuovo oggetto non ne aumenta nessuno. E 'questo in qualche modo collegato a 'aliasing', come ad esempio: #we hanno 1 oggetto in memoria e 1 alias ad esso obj1 = Object.new obj1.freeze obj1 = Object.new # obj1 ora punta ad un altro oggetto, ma la memoria per il primo oggetto è ancora "congelata"? Ho capito bene? –

+0

@FilipZymek Hai capito. :) – toro2k

+0

Ok, questo ha perfettamente senso ora, grazie! –

17

In Ruby, le variabili sono riferimenti a oggetti. Si blocca l'oggetto, non la variabile.

Si prega di notare, inoltre, che

a = [1, 2] 
a.freeze 
a += [3] 

non è un errore perché + per gli array crea un nuovo oggetto.

+0

Lo stesso per le stringhe. +1 per la risposta. '' 'ruby a = 'test'.freeze # =>" test " a.frozen? # => true a << '1' # RuntimeError: impossibile modificare la stringa congelata a + = '1' # => "test1" '' ' – kode

12

Come indicato nelle altre due risposte, si congelano oggetti anziché variabili.

Vorrei aggiungere una nota sugli oggetti figlio, che non vengono congelati quando il genitore è congelato. Questo può mordere difficile se non si presta attenzione a quello che stai facendo, quando si espone le strutture interne di un oggetto:

class A 
    attr_accessor :var 
end 

a = A.new 
a.var = [] 
a.freeze 
a.var = [] # this fails as expected 
a.var << :a # this works, raises no errors, and no warnings 

potete leggere il razionale qui:

https://bugs.ruby-lang.org/issues/6037

+0

questo è utile suggerimento grazie! –

Problemi correlati