我想知道为什么调用operator方法不需要点?或者更确切地说,为什么没有点可以调用普通方法?
实施例
class Foo def +(object) puts "this will work" end def plus(object) puts "this won't" end end f = Foo.new f + "anything" # "this will work" f plus "anything" # NoMethodError: undefined method `plus' for main:Object
答案 0 :(得分:12)
对于这个问题的答案,就每个语言设计问题而言:“只是因为”。语言设计是一系列主要的主观权衡。对于大多数主观权衡,唯一正确回答问题的原因是什么,只是“因为Matz这么说”。
当然还有其他选择:
Lisp根本没有运营商。 +
,-
,::
,>
,=
等等只是普通的法律函数名称(实际上是变量名称),就像{{1 }或foo
bar?
Smalltalk 几乎没有运营商。 Smalltalk唯一的特殊外壳是,只包含操作符的方法不必以冒号结尾。特别是,由于没有运算符,所有方法调用都具有相同的优先级,并且严格按从左到右的方式进行评估:(plus 1 2)
(+ 1 2)
为2 + 3 * 4
,而不是20
。
14
Scala 几乎没有运营商。就像Lisp和Smalltalk一样,1 plus: 2
1 + 2
,*
,-
等等只是合法的方法名称。 (实际上,它们也是合法的类,特征,类型和字段名称。)任何方法都可以使用或不使用点调用。如果您使用不带点的表单,并且该方法只接受一个参数,那么您也可以不使用括号。尽管Scala 具有优先权,但它不是用户可定义的;它只是由名字的第一个字符决定。另外,以冒号结尾的运算符方法名称是反转的或右关联的,即#:::
等同于a :: b
而不是b.::(a)
。
a.::(b)
在Haskell中,名称由运算符符号组成的任何函数都被视为运算符。通过将任何函数封装在反引号中,可以将任何函数视为运算符,并且可以通过将任何运算符括在括号中来将其视为函数。此外,程序员可以自由地为用户定义的运算符定义关联性,固定性和优先级。
1.plus(2)
1 plus(2)
1 plus 2
1.+(2)
1 +(2)
1 + 2
没有特别的理由说明Ruby不能以类似于Scala的样式支持用户定义的运算符。 是为什么Ruby不能在操作员位置支持任意方法的原因,仅仅因为
plus 1 2
1 `plus` 2
(+) 1 2
1 + 2
已经合法,因此这将是一种向后兼容的变化。
另一件需要考虑的事情是Ruby实际上并没有事先完全设计好。它是通过实施而设计的。这意味着在很多地方,实施都在泄漏。例如,
绝对没有逻辑上的原因foo plus bar
合法,但
puts(!true)
是没有的。唯一的原因为什么这是因为,因为Matz使用LALR(1)解析器来解析非LALR(1)语言。如果他先设计了语言,他就不会在第一时间选择一个LALR(1)解析器,而且表达式是合法的。
目前正在puts(not true)
讨论的Refinement
功能是另一个例子。当前指定的方式将使不可能优化方法调用和内联方法,即使相关程序实际上并未实际使用ruby-core
。只需进行简单的调整,它就可以表达和强大,和确保只有实际使用 Refinement
的范围才会产生悲观化成本。显然,为什么以这种方式指定的唯一原因是a)以这种方式原型更容易,并且b)YARV不拥有优化器,所以没有人甚至不屑于考虑其影响(好吧,除了Charles Oliver Nutter之外没有人)。
因此,对于基本任何问题,你有关于Ruby的设计,答案几乎总是“因为Matz这样说”或“因为在1993年它更容易实现这种方式”。 / p>
答案 1 :(得分:8)
实现没有允许新运算符的通用定义所需的额外复杂性。
相反,Ruby有一个使用静态定义语法的Yacc解析器。你得到了内置的运营商,就是这样。符号出现在语法中的一组固定句子中。正如您所指出的,运算符可以过载,这比大多数语言都要多。
当然不是因为Matz很懒。
Ruby实际上有一个非常复杂的语法,大致处于Yacc可以实现的极限。要想变得更复杂,需要使用不太便携的编译器生成器,或者需要在C中手动编写解析器,并且 将以自己的方式限制未来的实现可移植性以及不提供带有Yacc输入的世界。这将是一个问题,因为Ruby的Yacc源代码是唯一的Ruby语法文档,因此是“标准”。
答案 2 :(得分:3)
因为Ruby具有“语法糖”,允许为预设情况提供各种方便的语法。例如:
class Foo
def bar=( o ); end
end
# This is actually calling the bar= method with a parameter, not assigning a value
Foo.new.bar = 42
以下是可以作为Ruby中的方法实现的operator expressions列表。
答案 3 :(得分:2)
因为Ruby的语法设计看起来大致像流行的OO语言,并且那些使用点运算符来调用方法。它从Smalltalk借用其对象模型的语言并没有使用点作为消息,事实上它有一种相当“怪异”的语法,许多人发现这种语法很不合适。 Ruby被称为“具有Algol语法的Smalltalk”,其中Algol是一种语言,它为我们提供了您在此处讨论的约定。 (当然,实际上存在的差异不仅仅是Algol语法。)
答案 4 :(得分:0)
缺少大括号对于ruby 1.8来说是一个“优势”,但是对于ruby 1.9,你甚至不能写method_0 method_1 some param
它会被拒绝,所以语言更倾向于严格版本而不是自由形式。