简体   繁体   中英

Confusion with method call from IRB in Ruby

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"

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, ie 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 .)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM