Reputation: 118299
I was playing with method definition and calling to them in the main
of IRB.
def show
p "hi"
end
#=> nil
show
#"hi"
#=> "hi"
self.show
#"hi"
#=> "hi"
The above are good and understood.
Now let's try something different:
def Foo
p "hi"
end
#=> nil
Foo
#NameError: uninitialized constant Foo
#from (irb):4
#from C:/Ruby193/bin/irb:12:in `<main>'
While the call to Foo
has thrown an error as above,how does the below remove that?
self.Foo
#"hi"
#=> "hi"
Upvotes: 2
Views: 681
Reputation: 369623
In Ruby, you can call methods without a receiver and without an argument list. However, this means that there is an ambiguity: does foo
mean "call method foo
on the implicit receiver self
without arguments, i.e. equivalent to self.foo()
" or does it mean "dereference the variable foo
"? Ruby can't know which you mean, so there are some simple rules.
For a local variable, the rule is that foo
is always a method call, unless foo
is statically known at parse time to be a local variable. So, when is it statically known to be a variable? When there was an assignment to that variable which was parsed (but not necessarily executed!) before the use.
Example:
foo # method call
if false
foo = 42 # will never be executed, but *will* be parsed
end
foo # variable dereference, since the `foo` assignment was parsed
For constant variables, the rule is even simpler: Foo
is always interpreted as a constant dereference. Period.
So, how do you call a method with such a name? Easy: like I said, the ambiguity arises only for method calls with no argument list and no explicit receiver. So, if we add either one or both of those, Ruby will know that we are trying to call a method and not dereference a variable:
foo()
self.foo
self.foo()
Foo()
self.Foo
self.Foo()
Of course, in the example you gave above, only the first one will work. When you define a method at the top-level, it is added as a private
method to Object
, and private
methods can only be called without an explicit receiver, even if that receiver is self
. So, self.Foo
won't work, because Foo
is private. (Except in IRb, where, for convenience reasons, top-level methods are public
.)
Upvotes: 4