Difference between inline if conditional and block if condition in Ruby

Today I come across this weird behavior of Ruby 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?

+6
source share
3 answers

See Local Variables and Methods :

A local variable is created when the parser encounters an assignment, not an assignment:

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

In the first example, inline_if occurs first in the assignment, so it is created (and has the value nil ). While in the second example, block_if displayed in the condition before it sees an assignment, which causes an error.

+2
source

I suspect he has something with a ruby ​​parser. Because when writing a line, if

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

The Ruby parser actually parses from left to right. Therefore, in the above line, he first encounters the setter method of the inline_if variable. therefore, it actually defines this variable with the value nil , and then checks the if inline_if condition, which will evaluate to if nil .

Now with the block if the condition

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

first tries to access the variable block_if , which is not yet defined. therefore, this will result in an error.

Surprisingly, from the point of view of the programmer, both of the above blocks should be evaluated equally. but they behave differently

+2
source

"The Ruby interpreter initializes a local variable with zero when it sees its purpose." See this answer in a related simpler question that highlights the important part of the behavior you see.

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

Also, watch this hilarious video about JavaScript and Ruby errors!

+1
source

Source: https://habr.com/ru/post/978229/


All Articles