2014-11-15 29 views
6

Oggi ho incontrato questo strano comportamento della linea di Ruby se e bloccare seDifferenza tra linea se condizionale e il blocco se condizionale in Ruby

2.0.0-p247 :001 > inline_if = 'value will not set but no error' if inline_if 
=> nil 
2.0.0-p247 :002 > if block_if 
2.0.0-p247 :003?> block_if = 'forget about setting value, I will raise an error' 
2.0.0-p247 :004?> end 
NameError: undefined local variable or method `block_if' for main:Object 
    from (irb):2 
    from /Users/myuser/.rvm/rubies/ruby-2.0.0-p247/bin/irb:13:in `<main>' 

Qual è la differenza tra linea se condizionato e blocco se condizionale?

+0

Dove hai definito 'block_if'? – Santhosh

+0

'inline_if' e' block_if' non sono definiti. Ma usando il blocco se l'istruzione genera un errore mentre in linea non genera alcun errore. – Hardik

+1

Eccone un altro: 'a = b.nil? => NameError: variabile locale non definita o metodo 'b' per main: Object', ma 'a = a.nil? => true'. @YuHao spiega perché. Verso la fine di uno dei suoi [articoli] sempre interessanti (http://www.rubyinside.com/what-rubys-double-pipe-or-equals-really-does-5488.html), Peter Cooper ha messo questo modo: "Cioè, un assegnamento variabile, anche se non eseguito, richiama immediatamente quella variabile in essere." Domanda interessante –

risposta

2

Vedi Local Variables and Methods:

The local variable is created when the parser encounters the assignment, not when the assignment occurs:

a = 0 if false # does not assign to a 
p local_variables # prints [:a] 
p a    # prints nil 

Nel primo esempio, inline_if incontrato prima assegnazione, quindi viene creato (e ha un valore di nil). Mentre nel secondo esempio, block_if viene visualizzato nella condizione prima di essere visto nell'assegnazione, che causa l'errore.

+0

Questo è quello che sospettavo, che il parser deve definire la variabile anche se l'istruzione non viene eseguita. Grazie per la tua risposta. – Hardik

2

Ho il sospetto che abbia qualcosa con parser rubino. Perché quando si scrive in linea se

inline_if = 'value will not set but no error' if inline_if 

Il parser di ruby ​​viene analizzato da sinistra a destra. Quindi nella riga sopra si incontra per prima cosa il metodo setter della variabile inline_if. quindi in realtà definisce questa variabile con il valore nil e quindi controlla la condizione if inline_if che verrà valutata come if nil.

Ora con il blocco se la condizione

if block_if 
    block_if = 'forget about setting value, I will raise an error' 
end 

tenta innanzitutto di accedere alla variabile block_if che non è ancora definito. quindi tederà un errore.

È sorprendente che dalla visualizzazione del programmatore entrambi i blocchi precedenti debbano essere valutati allo stesso modo. ma si comportano diversi

1

"L'interprete Ruby inizializza una variabile locale con zero quando vede un incarico ad esso." Vedi this answer in una domanda più semplice che mette in evidenza la parte cruciale del comportamento che stai vedendo.

> a = a 
# => nil (and assigns nil to a) 
> b = c 
# => NameError... 

Inoltre, guardare questo esilarante video su JavaScript e Ruby stranezze!