NameError: undefined - have parsing rules for local variables changed in Ruby 2.1.2?
Yes it changed in ruby 2.1.2
In 1.8.7
, 1.9.3
, 2.0.0
and even 2.1.1
I get 2 warnings and no errors:
2.0.0-p247 :007 > bar if bar = false
(irb):7: warning: found = in conditional, should be ==
=> nil
2.0.0-p247 :008 > bar if bar = true
(irb):8: warning: found = in conditional, should be ==
=> true
whereas in the 2.1.2
version you mention I get 2 warnings and 1 NameError
error.
2.1.2 :001 > bar if bar = true
(irb):1: warning: found = in conditional, should be ==
NameError: undefined local variable or method `bar' for main:Object
from (irb):1
from /home/durrantm/.rvm/rubies/ruby-2.1.2/bin/irb:11:in `<main>'
2.1.2 :002 > bar if bar = false
(irb):2: warning: found = in conditional, should be ==
=> nil
This is on my Ubuntu 14
Why is assignment treated differently in this single line conditional?
Oddly enough, this works fine in Rubinius:
Welcome to IRB. You are using rubinius 1.2.4dev (1.8.7 7ae451a1 yyyy-mm-dd JI)
>> (puts x) if (x = 0) #=> nil
0
I'm inclined to say it's a weird parsing bug in MRI.
Variable scope and order of parsing vs. operations: Assignment in an if
It only happens when you try to assign a literal value, if you call a function it works.
def foo(a)
a
end
p 'not shown' if(value = foo(false))
p 'shown' if(value = foo(true))
# This outputs a Warning in IRB
p 'shown' if(value = false)
(irb):2: warning: found = in conditional, should be ==
If you turn on debugging (-d) you will see a warning about an used variable value
warning: assigned but unused variable - value
This "works" because the statement does evaluate to true
as far as if is concerned, allowing the code preceeding it to run.
What is happening here is that if() when used as a modifier has it's own binding scope, or context. So the assignment is never seen outside of the if, and therefore makes no sense to perform. This is different than if the control structure because the block that the if statement takes is also within the same scope as the assignment, whereas the line that preceeded the if modifier is not within the scope of the if.
In other words, these are not equivelant.
if a = some(value)
puts a
end
puts a if(a = some(value))
The former having puts a
within the scope of the if, the latter having puts a
outside the scope, and therefore having different bindings(what ruby calls context).
Ruby Order of Operations
How come (a_method || :other) returns :other only when assigning to a var called a_method?
There have been similar questions, but not exactly the same. Jörg's answer here seems to hit the point, I'm quoting the relevant part:
At this point,
foo
is defined, even
though the line will never get
executed. The fact that the line never
gets executed is completely
irrelevant, because the interpreter
has nothing to do with this anyway:
local variables are defined by the
parser, and the parser obviously sees
this line.
So, in your case, regardless of the fact that a method with the same name already exists, the parser sees some_method
assignment and it automatically "tags" the identifier to be local variable. So, when interpreter starts evaluating the right-hand-side of the assignment, it already considers some_method
to be local variable, not a method. Its value is unassigned (nil
by default), so the result of ||
will be :other
.
Why does capturing named groups in Ruby result in undefined local variable or method errors?
Named Captures Must Use Literals
You are encountering some limitations of Ruby's regular expression library. The Regexp#=~ method limits named captures as follows:
- The assignment does not occur if the regexp is not a literal.
- A regexp interpolation,
#{}
, also disables the assignment. - The assignment does not occur if the regexp is placed on the right hand side.
You'll need to decide whether you want named captures or interpolation in your regular expressions. You currently cannot have both.
Related Topics
Getting a Rogue Iteration from My .Each Loop
Instance_Eval Does Not Work with Do/End Block, Only with {}-Blocks
Can't Dup Nilclass on Association Methods
Bootstrap Modal in Ruby on Rails Not Working
Ruby Parenthesis Syntax Exception with I++ ++I
Convert Spreadsheet Column Index into Character Sequence
Rails: Chartkick Cummulative User Graph
404 Resource Not Found: Domain with Google Directory API
Mini_Magick Gem Doesn't Work with My Imagemagick Install
Problems with Jslint-V8 Ruby Gem Installation on Windows7 64-Bit
Calling Instance Variables Without @
Stubbing Controller Actions in Rspec Request Specs
How to Sort So That "Vitamin B12" Is Not in Front of "Vitamin B6"
Undefined Method Error When Creating Delayed_Job Workers with Script/Delay_Job
Import CSV in Batches of Lines in Rails
How to Mix Required Argument and Optional Arguments in Ruby