2011-12-14 16 views
7

Se eseguo questo codice ruby:Rubino: metodo inspiegabilmente sovrascritti e impostare a zero

def foo 
    100 
end 

p defined?(foo), foo 
if false 
    foo = 200 
end 
p defined?(foo), foo 

L'output che ottengo è:

"method" 
100 
"local-variable" 
nil 

Qualcuno può spiegarmi perché foo è impostato su nil dopo non aver eseguito l'if? Questo comportamento atteso o un bug rubino?

+1

Il metodo non viene sovrascritto e impostato a zero. 'puts foo()' funziona ancora. Quello che succede è che una variabile locale 'pippo' è entrata in esistenza. Ci dispiace, ma non posso rispondere perché questo accade. – Mischa

+0

Anche io non so rispondere perché. Ma se c'è sempre un'ambiguità tra variabili e metodi locali, assicurarsi di utilizzare 'self.foo' per il metodo, e' foo' per la variabile. –

+0

@sawa - non voglio far ritirare di nuovo, ma non capisco il tuo commento e non capisco il motivo per cui è stata modificata la domanda di bmesuere. Non c'è niente di sbagliato nella domanda. Non vedo la necessità di modificarlo. – Mischa

risposta

5

I nomi sul lato sinistro delle assegnazioni vengono impostati su nil, anche se il codice non può essere raggiunto come nel caso if false.

>> foo 
NameError: undefined local variable or method `foo' for main:Object 
... 
>> if false 
.. foo = 1 
.. end #=> nil 
>> foo #=> nil 

Quando Rubino prova a risolvere le bareword, in primo luogo sembra per le variabili locali (c'è un riferimento a tale nel libro Piccone, che io non riesco a trovare in questo momento). Dal momento che ora avete uno chiamato foo si visualizza nil. Come rilevato da Mischa, il metodo può ancora essere chiamato come foo().

+0

Se capisco bene, viene creata una variabile locale 'foo' mentre ruby ​​analizza il codice, anche quando quel codice potrebbe non essere mai eseguito? – bmesuere

+2

Fintanto che la variabile si trova sul lato sinistro di un compito, sì. BTW: dato che sei nuovo di SO, l'etichetta qui è di upvotare e/o accettare risposte utili. Se hai ulteriori domande, sono felice di aggiornare la mia risposta. –

+0

Mi dispiace, non ero molto chiaro nel mio precedente commento. Intendevo chiedere se la variabile fosse solo "riservata" durante l'analisi, o se fosse allocata anche la memoria (che sembra terribilmente inefficiente)? – bmesuere

1

Questo è ciò che avevano da dire il mio amico e Ruby super-esperto di Josh Cheek:

Quando Rubino vede l'assegnazione, si inizializza la variabile nell'ambito corrente e lo imposta a zero. Poiché il compito non è stato eseguito, non ha aggiornato il valore di foo.

if non cambiano portata come i blocchi fanno. Questa è anche la differenza più importante tra

for x in xs 

e

xs.each { |x| } 

Ecco un altro esempio:

a = 123 if a # => nil 
a # => nil 

Non dovremmo essere in grado di dire if a perché non abbiamo mai fissato a, ma rubino vede l'a = 123 e inizializza a, poi arriva a if a a quel punto a è nil

lo considererei un capriccio dell'interprete, davvero. Gary Bernhardt prende in giro in wat (https://www.destroyallsoftware.com/talks/wat) con a = a

-Josh