2012-02-02 10 views
5

Eventuali duplicati:
Why a = a is nil in Ruby?Perché posso assegnare una variabile indefinita a se stessa in Ruby e ottenere nulla?

C'è una, per così dire, "fenomeno strano" in Ruby con l'utilizzo di variabili indefinite. E 'in questo modo:

# irb session follows 
# 
foo  # undefined local variable or method 'foo' 
bar  # same for 'bar' 
foo = bar # still same for 'bar' 
foo = foo # nil - HUH? 
foo  # is now set to nil!? 

Perché posso assegnare una variabile non definita a se stesso in Ruby e ottenere nil?

Nota che sto usando Ruby 1.9.3 qui. Non sono sicuro di quali altre versioni questo può essere vero in.

(grazie a Gary Bernhardt per dimostrare questo nel suo hilarious talk.)

+1

Presumibilmente, 'foo = foo' viene valutato in due passaggi. Il primo "dichiara" la variabile con un valore predefinito, e il secondo lo assegna a se stesso. – millimoose

risposta

2

Nil è magia in Ruby, per l'idea che ogni cosa è un oggetto . In realtà c'è un oggetto singleton nil che viene assegnato. Quando hai fatto

foo = bar 

il "foo" Sprang variabile in esistenza e ha preso come valore di oggetto nullo magia. Prima di eseguire l'incarico, Ruby non aveva modo di "sapere" che cosa è foo (è una variabile? Una chiamata di metodo?), Ma una volta eseguito il compito, inizia a trattarlo come una variabile.

+0

Bene, 'foo = foo' funziona anche senza dichiarazioni precedenti. –

+0

Lo fa sicuramente, e per lo stesso motivo. Il nullo non è la cosa - è solo un segnaposto per un valore indefinito. La cosa è il compito, una volta che Ruby vede il compito, "decide" di trattare il token a sinistra del "=" come variabile. – theglauber

+1

@theglauber, Questo non spiega abbastanza 'foo = foo'. Nel caso di 'foo = bar' se sia foo che bar non sono definiti, viene comunque sollevata un'eccezione. Il caso strano del funzionamento di 'foo = foo' è dovuto al fatto che l'interprete ruby ​​esegue l'inizializzazione prima della valutazione dell'espressione. Essenzialmente sulla mano sinistra, foo è adattato a zero; quindi, quando l'interprete raggiunge la valutazione dell'espressione per eseguire l'assegnazione, il foo sul lato destro è già stato inizializzato. – bigtunacan

7

Il fatto che la barra non è definito, non è in realtà la parte più interessante, dal momento che la cessione non ha nemmeno bisogno di essere tentato, ad esempio

if false 
    foo = 1 
end 

Imposta pippo a zero. A quanto ho capito, l'ambito della variabile locale viene determinato staticamente in quanto viene determinato senza effettivamente eseguire il codice, semplicemente analizzandolo. Ruby pensa che il compito potrebbe accadere, quindi crea la variabile locale e la imposta su zero. Vedi http://ruby.runpaint.org/variables#local

+0

Ancora meglio, la variabile da assegnare nell'istruzione if non deve essere definita: 'foo = wat se false' –