Ruby 当方法调用原则上可以是常量时,为什么需要消除歧义?
方法调用通常可以忽略接收方和参数的括号:Ruby 当方法调用原则上可以是常量时,为什么需要消除歧义?,ruby,methods,syntax,constants,Ruby,Methods,Syntax,Constants,方法调用通常可以忽略接收方和参数的括号: def foo; "foo" end foo # => "foo" 在上面的例子中,foo在方法调用和对潜在局部变量的引用之间是不明确的。如果没有后者,则将其解释为方法调用 然而,当方法名称原则上可以是一个常量名称时(即,当它以大写字母开头,并且仅由字母组成时),似乎需要消除歧义 def Foo; "Foo" end Foo # => NameError: uninitialized constant Foo Foo() # => "
def foo; "foo" end
foo # => "foo"
在上面的例子中,foo
在方法调用和对潜在局部变量的引用之间是不明确的。如果没有后者,则将其解释为方法调用
然而,当方法名称原则上可以是一个常量名称时(即,当它以大写字母开头,并且仅由字母组成时),似乎需要消除歧义
def Foo; "Foo" end
Foo # => NameError: uninitialized constant Foo
Foo() # => "Foo"
self.Foo # => "Foo"
为什么会这样?为什么即使在没有同名常量的情况下,方法调用也需要与常量引用明确区分开来?您提出了一个很好的问题。正如您所指出的,ruby希望将其视为常量,因此执行常量查找 但是,下面的代码片段显示了当前的行为,然后通过修改const_missing,您似乎获得了所需的行为。跟你说实话,我似乎什么也没打破 我的结论是,正如有人已经建议的那样,这只是一个设计决策,但这很奇怪,因为一般来说ruby支持约定而不是强制执行 或者我错过了一些情况,事情变得混乱,错误的事情发生了
外汇基金票据及债券;元素['#output'].html=元素['#output'].html+s.to_.gsub(“\n”,“
”).gsub(“,”)+“
”;结束
阶级
def self.to_
“我是伊玛班的”
结束
结束
定义IMA方法
“你好”
结束
不知道什么课
def self.to_
“一个班级”
结束
结束
def DontKnowWhatIAm
“一种方法”
结束
放置“ImAClass:#{ImAClass}”
开始
放置“ImAMethod:#{ImAMethod}”
救援异常=>e
放入“混乱!#{e.message}”
结束
放置“ImAMethod():#{ImAMethod()}”
将“DontKnowWhatIAm:#{DontKnowWhatIAm}”
放置“DontKnowWhatIAm():#{DontKnowWhatIAm()}”
类模块
别名\u方法:旧的\u常量\u缺失,:常量\u缺失
def const_缺失(c)
如果self.response\u?C
自我发送
其他的
旧建筑失踪(c)
结束
结束
结束
福班
def自动控制杆
“我在酒吧”
结束
结束
放置“现在我们可以说:Foo::Bar,它就工作了!#{Foo::Bar}”
程序中任何给定点范围内的局部变量集都是按词汇定义的,因此可以静态确定,甚至早在解析时就可以确定。因此,Ruby甚至在运行之前就知道哪些局部变量在作用域中,因此可以区分消息发送和局部变量取消引用
常量首先通过词汇查找,然后通过继承(即动态)查找。运行前不知道哪些常量在作用域中。因此,为了消除歧义,Ruby总是假定它是一个常量,除非它显然不是,即它接受参数或有接收器或两者兼有。这种差异背后没有什么大的原因。我只是希望foo的行为像foo(),如果作用域中没有局部变量foo的话。我认为它对创建DSL等很有用,但我认为没有理由让Foo表现得像Foo()。谢谢你的回答。事实上,局部变量是在解析时定义的,这就是为什么
如果为false,那么Foo=43 end;foo#=>nil(而不是namererror)
@JörgWMittag这很有道理。那么这是为了提高效率?换言之,如果我们随意使用以大写字母开头的方法,那么所有这些方法都必须经过消歧过程。如果出于某种原因需要,您可以重写该行为(如我的答案所示)这是一个很好的答案。@MitchVanDuyn:真正的危险在于,您无法控制的第三方库只需在继承链的某个位置引入一个常量,就可以更改代码的含义。真令人惊讶!本物の松本さんですか。