Reputation:
The output of the following snippet of Ruby code
def foo; "foo:function"; end
puts foo
puts foo()
foo = "foo:value"
puts foo
puts foo() # Didn't expect this to work!
is
foo:function
foo:function
foo:value
foo:function
This is puzzling, I would have thought that in the current scope there is only one binding for foo, but looks like this is not the case.
PS: Running equivalent code in python gives the expected result (i.e. after binding a string to foo, the last statement trying to call foo() gives an error).
Edit:
The following is the equivalent example in python:
def foo(): return "foo:function"
print foo
print foo()
foo = "foo:value"
print foo
print foo()
which produces the output (edited):
<function foo at 0x7fb71d912578>
foo:function
foo:value
TypeError: 'str' object is not callable
Edit 2:
So, it seems in Ruby, unlike Python, a given symbol can have two binds in the same scope (as a method and as an instance variable).
Upvotes: 2
Views: 97
Reputation: 8424
Try puts foo without the parentheses and you'll get "foo:value". With the () you're explicitly saying this is a method. Try putting these 2 lines at the end of your code:
puts defined? foo #=> local-variable
puts defined? foo() #=> method
You may find this SO answer to be useful, especially this part:
Why does it make sense for local variables to "shadow" methods and not the way around? Well, if methods did shadow local variables, there would no longer be a way to dereference those local variables. However, if local variables shadow methods, then there is still a way to call those methods: remember, the ambiguity only exists for receiverless argumentless methods calls, if you add an explicit receiver or an explicit argument list, you can still call the method:
Upvotes: 2