Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does a method call need to be disambiguated when it can in principle be a constant?

Method calls can usually omit the receiver and the parentheses for the arguments:

def foo; "foo" end
foo # => "foo"

In the case above, foo is ambiguous between method call and reference to a potential local variable. In the absence of the latter, it is interpreted as a method call.

However, when the method name can in principle be a constant name (i.e., when it starts with a capital letter, and consists only of letters), it seems to need disambiguation.

def Foo; "Foo" end
Foo # => NameError: uninitialized constant Foo
Foo() # => "Foo"
self.Foo # => "Foo"

Why is this the case? Why does a method call need to be explicitly distinguished from a reference to a constant even under the absence of a constant with the same name?

like image 842
sawa Avatar asked Jan 07 '16 14:01

sawa


People also ask

What happens when method is called?

When a method is invoked (called), a request is made to perform some action, such as setting a value, printing statements, returning an answer, etc. The code to invoke the method contains the name of the method to be executed and any needed data that the receiving method requires.

What happens when you call a method in Ruby?

A method in Ruby is a set of expressions that returns a value. With methods, one can organize their code into subroutines that can be easily invoked from other areas of their program. Other languages sometimes refer to this as a function.


2 Answers

The set of local variables which is in scope at any given point in the program is defined lexically and can thus be determined statically, even as early as parse time. So, Ruby knows even before runtime which local variables are in scope and can thus distinguish between a message send and a local variable dereference.

Constants are looked up first lexically, but then via inheritance, i.e. dynamically. It is not known which constants are in scope before runtime. Therefore, to disambiguate, Ruby always assumes it's a constant, unless obviously it isn't, i.e. it takes arguments or has a receiver or both.

like image 74
Jörg W Mittag Avatar answered Oct 07 '22 06:10

Jörg W Mittag


There's no big reason behind the difference. I just wanted foo to be behave like foo(), if there's no local variable foo in the scope. I thought it was useful for creating DSL etc. But I saw no reason to make Foo to behave like Foo().

like image 21
Yukihiro Matsumoto Avatar answered Oct 07 '22 05:10

Yukihiro Matsumoto