If you run your snippet with debugging on (-d) you will see a warning
about an unused variable...
For example:
Your example doesn't show such a warning.
# foo_bar.rb
foo = 1
puts foo
puts "foo is 1" if foo == 1
puts "bar is 1" if bar != 1
# => Exception `NameError' at foo_bar.rb:6 - undefined local variable
or method `bar' for main:Object
if() when used as a modifier has its own context... its scope.
So the assignment is never seen outside of the if and 'bar' it's undefined.
I believe this is incorrect and sows confusion. In reality, the reason `puts
a if a = 0.zero?` fails if a hasn't been defined is because the parser
scans strictly from left to right looking for assignments. When it finds an
assignment, it considers the left side of that assignment to be a valid
variable from there to the end of the scope. It doesn't backtrack into the
portion of the line before a modifier-if, so `puts a` is unable to resolve
the variable a.
···
On Sat, Feb 8, 2014 at 9:57 AM, Edoardo Rossi <edd.rossi@gmail.com> wrote:
This works:
if (bar = 1+1) == 2
puts "bar is 2? yup! (#{bar})"
end
because the block that the if statement takes is also within the same
scope as the assignment.
.
Hope it helps
On Sat, Feb 8, 2014 at 4:30 PM, Arup Rakshit <lists@ruby-forum.com> wrote:
> Look the below code
>
> (arup~>~)$ pry --simple-prompt
>>> x = 1
> => 1
>>> puts "x is 1" if x == 1
> x is 1
> => nil
>>> puts "x is 1" if x != 1
> => nil
>
> The above code is telling, first checking the conditions, then execute
> the body `puts ...`. I agree this, why then error from the below code ?
>
>>> puts a if a = 0.zero?
> NameError: undefined local variable or method `a' for main:Object
> from (pry):4:in `__pry__'
>
> --
> Posted via http://www.ruby-forum.com/\.
if() when used as a modifier has its own context... its scope.
So the assignment is never seen outside of the if and 'bar' it's
undefined.
But 'a' gets defined after the error. Does it mean that it first gets
defined in the inner scope and passed to the outer scope?
[1] pry(main)> puts a if a = 0.zero?
NameError: undefined local variable or method `a' for main:Object
from (pry):1:in `__pry__'
[2] pry(main)> a
=> true
[3] pry(main)>
If anything that is defined gets into this inner scope and anything that
is defined (or modified) inside the inner scope gets out, then this is
not really a scope...
Because the assignment of x happens and it's not lost...
puts "x before all: "
puts "#{x.inspect}" rescue puts "x is nil"
puts "x before the if: "
puts "#{x.inspect}" if(x = 2) rescue puts "x is still nil"
puts "but x after the if: #{x.inspect}"
···
On Sat, Feb 8, 2014 at 5:13 PM, Arup Rakshit <lists@ruby-forum.com> wrote:
Edoardo Rossi wrote in post #1136041:
Hi Arup.
if() when used as a modifier has its own context... its scope.
So the assignment is never seen outside of the if and 'bar' it's
undefined.
See another snippet :
puts "hi" if x = 2
(pry):11: warning: found = in conditional, should be ==
hi
=> nil
[1] pry(main)> puts a if a = 0.zero?
NameError: undefined local variable or method `a' for main:Object
from (pry):1:in `__pry__'
[2] pry(main)> a
=> true
[3] pry(main)>
If anything that is defined gets into this inner scope and anything that
is defined (or modified) inside the inner scope gets out, then this is
not really a scope...
Another example, which doesn't create a noise like local variable in my
first post.
I think this is because _method_ lookup is different from _variable_
lookup in Ruby.
Try this on a file (because inside pry or irb is hard to deal with
method_missing).
#!/usr/bin/env ruby
# If no local variable is found,
# it begins the method lookup that ends calling
# the method_missing chain until the last one raises the error
begin
p undefined_name if true
rescue
puts "Raised an error"
else
puts "No error at all"
end
def method_missing(method, *args)
"I'm a method"
end
# When no method is found,
# It hits the method_missing and do what is defined on it
# so... returns "I'm a method" without raising any errors.
puts
begin
p undefined_name if true
rescue
puts "Raised an error"
else
puts "No error at all"
end
undefined_name = "I'm a local-variable"
# Now a local-variable with the same name is found (before the method)
puts
begin
p undefined_name if true
rescue
puts "Raised an error"
else
puts "No error at all"
end
# If we need to disambiguate it, for the method we need to prepend the
object will be sending it to.
# self.undefined_name vs. undefined_name
puts
begin
p self.undefined_name if true
rescue
puts "Raised an error"
else
puts "No error at all"
end
Abinoam Jr.
···
On Sat, Feb 8, 2014 at 8:15 PM, Arup Rakshit <lists@ruby-forum.com> wrote:
Földes László wrote in post #1136082:
Edoardo Rossi wrote in post #1136041:
[1] pry(main)> puts a if a = 0.zero?
NameError: undefined local variable or method `a' for main:Object
from (pry):1:in `__pry__'
[2] pry(main)> a
=> true
[3] pry(main)>
If anything that is defined gets into this inner scope and anything that
is defined (or modified) inside the inner scope gets out, then this is
not really a scope...
Another example, which doesn't create a noise like local variable in my
first post.