为什么方法调用在原则上可以是常量时需要消除歧义?

方法调用通常可以省略接收器和参数的括号:

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

在上面的例子中, foo在方法调用和对潜在局部变量的引用之间是不明确的。 在没有后者的情况下,它被解释为方法调用。

但是,当方法名称原则上可以是常量名称时(即,当它以大写字母开头,并且仅包含字母时),它似乎需要消除歧义。

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

为什么会这样? 为什么即使没有具有相同名称的常量,也需要将方法调用与对常量的引用明确区分开来?

在程序中任何给定点的范围内的局部变量集是词法定义的,因此可以静态地确定,甚至早在解析时间。 因此,Ruby甚至在运行时之前就知道哪些局部变量在范围内,因此可以区分消息发送和本地变量解除引用。

首先通过词法查找常量,然后通过inheritance查找,即动态地查找常量。 在运行时之前,不知道哪些常量在范围内。 因此,为了消除歧义,Ruby总是假定它是一个常量,除非显然不是,即它需要参数或有接收器或两者兼而有之。

差异背后没有大的理由。 我只是希望foo表现得像foo(),如果范围内没有局部变量foo。 我认为它对创建DSL等很有用。但我没有理由让Foo表现得像Foo()。

你问了一个很好的问题。 正如您所指出的,ruby希望将其视为常量,因此可以进行常量查找。

但是,以下代码段显示了当前行为,然后通过修改const_missing,您似乎获得了所需的行为。 而且说实话我似乎无法破坏任何东西。

我的结论是,这是有人已经建议的,只是一个设计决定,但它很奇怪,因为一般来说,ruby赞成惯例与执法。

或者我错过了一些事情让事情变得混乱而且错误的事情发生的情况。