Ruby: method inexplicably overwritten and set to nil

ぃ、小莉子 提交于 2019-11-30 07:31:41

问题


If I execute this ruby code:

def foo
  100
end

p defined?(foo), foo
if false
  foo = 200
end
p defined?(foo), foo

The output I get is:

"method"
100
"local-variable"
nil

Can someone explain to me why foo is set to nil after not executing the if? Is this expected behavior or a ruby bug?


回答1:


Names on the left hand side of assignments get set to nil, even if the code can't be reached as in the if false case.

>> foo
NameError: undefined local variable or method `foo' for main:Object
...
>> if false
..   foo = 1
..   end #=> nil
>> foo #=> nil

When Ruby tries to resolve barewords, it first looks for local variables (there's a reference to that in the Pickaxe book, which I can't seem to find at the moment). Since you now have one called foo it displays nil. As Mischa noted, the method still can be called as foo().




回答2:


This is what my pal and Ruby super-expert Josh Cheek had to say:

When Ruby sees the assignment, it initializes the variable in the current scope and sets it to nil. Since the assignment didn't get run, it didn't update the value of foo.

if statements don't change scope like blocks do. This is also the most important difference between

for x in xs

and

xs.each { |x| }

Here's another example:

a = 123 if a  # => nil
a  # => nil

We shouldn't be able to say if a because we never set a, but Ruby sees the a = 123 and initializes a, then gets to if a at which point a is nil

I'd consider it a quirk of the interpreter, really. Gary Bernhardt makes fun of it in wat (https://www.destroyallsoftware.com/talks/wat) with a = a

-Josh



来源:https://stackoverflow.com/questions/8505916/ruby-method-inexplicably-overwritten-and-set-to-nil

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!