2014-11-15 11 views
6

Heute komme ich über dieses seltsame Verhalten von Rubys inline wenn und blockiert, wennUnterschied zwischen inline wenn bedingte und Block, wenn bedingt 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>' 

Was ist der Unterschied zwischen Inline wenn bedingter und Block, wenn bedingt ist?

+0

Wo haben Sie 'block_if' definiert? – Santhosh

+0

'inline_if' und' block_if' sind beide nicht definiert. Aber mit der Anweisung block if wird ein Fehler ausgegeben, während inline kein Fehler auftritt. – Hardik

+1

Hier ist ein anderer: 'a = b.nil? => NameError: undefinierte lokale Variable oder Methode 'b' für main: Object', aber 'a = a.nil? => wahr '. @YuHao erklärt warum. Gegen Ende eines seiner immer-interessanten Artikel (http://www.rubyinside.com/what-rubys-double-pipe-or-equals-really-does-5488.html), Peter Cooper hat es so ausgedrückt Weg: "Das heißt, eine variable Zuweisung, auch wenn nicht ausgeführt, ruft sofort diese Variable ins Sein." Interessante Frage. –

Antwort

2

Local Variables and Methods Siehe:

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 

Im ersten Beispiel inline_if erste Begegnung in Zuordnung, so dass es erstellt wird (und hat einen Wert von nil). Während im zweiten Beispiel block_if in der Bedingung gesehen wird, bevor es in der Zuordnung gesehen wird, die den Fehler verursacht.

+0

Das ist, was ich vermutete, dass Parser die Variable definieren muss, selbst wenn die Anweisung nicht ausgeführt wird. Danke für deine Antwort. – Hardik

2

Ich vermute, es hat etwas mit Rubin-Parser. Denn beim Schreiben inline wird der Ruby-Parser tatsächlich von links nach rechts geparst. In der obigen Zeile trifft es zuerst auf die Setter-Methode der Variablen inline_if. daher definiert es diese Variable mit dem Wert nil und prüft dann auf die Bedingung if inline_if, die als if nil ausgewertet wird.

Jetzt mit dem Block, wenn die Bedingung

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

es versucht, zuerst die block_if Variable zuzugreifen, die noch nicht definiert ist. daher wird es einen Fehler verursachen.

Es ist erstaunlich, dass aus der Sicht des Programmierers beide oben genannten Blöcke gleichermaßen ausgewertet werden sollten. aber sie verhalten sich anders

1

Der "Ruby-Interpreter initialisiert eine lokale Variable mit Null, wenn eine Zuweisung dazu erkannt wird." Siehe this answer zu einer verwandten einfacheren Frage, die den entscheidenden Teil des Verhaltens, das Sie sehen, hervorhebt.

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

Auch watch this hilarious video über JavaScript und Ruby Seltsamkeiten!