Today I come across this weird behaviour of Ruby's inline if and block if
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>'
What is the difference between inline if conditional and block if conditional?
I suspect it has something to with ruby parser. Because when writing inline if
inline_if = 'value will not set but no error' if inline_if
Ruby parser actually parse from left to right. So in above line it first encounters setter method of variable inline_if
. so it actually defines this variable with value nil
and then it checks for the condition if inline_if
which will be evaluated as if nil
.
Now with the block if condition
if block_if
block_if = 'forget about setting value, I will raise an error'
end
it first tries to access the block_if
variable which is not yet defined. hence it will trow an error.
It's amazing thing that from programmer view both of above block should be evaluated equally. but they behave different
See 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
In the first example, inline_if
encountered first in assignment, so it is created(and has a value of nil
). While in the second example, block_if
is seen in the condition before it's seen in the assignment, which causes the error.
The "Ruby interpreter initializes a local variable with nil when it sees an assignment to it." See this answer to a related simpler question that highlights the crucial part of the behaviour you're seeing.
> a = a
# => nil (and assigns nil to a)
> b = c
# => NameError...
Also, watch this hilarious video about JavaScript and Ruby oddities!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With