我想创建下一个DSL部分:
* 'Ruby'
下一个实验显示了可预测的结果:
def *(a) a end * 'Ruby' #=> SyntaxError: (irb):4: syntax error, unexpected '\n', expecting :: or '[' or '.' self.*(1) #=> NoMethodError: private method `*' called for main:Object self.send(:*, 1) #=> 'Ruby'
我想Ruby语法分析器将这种表达式视为星号方法的splat运算符或语法糖.有人可以解释这个更详细和(如果可能)提供解决方案来解决我的问题?
那是不可能的.有些方法在没有显式接收器的情况下根本无法调用,因为否则它们会模糊不清.特别是,在你同时具有一元前缀和二进制中缀运算符的每种情况下,都不可能区分这两种情况:
+ a == a.+@() - a == a.-@() & a # interpreted as the unary prefix proc-block conversion operator * a # interpreted as the unary prefix splat operator
或者在运算符与其他语法冲突的情况下:
/ a # interpreted as the start of a Regexp literal
为了保持一致性,Ruby强制为所有二进制中缀运算符使用两个操作数,而不仅仅是语法不明确的操作符.
同样,[]
没有显式接收器也无法调用,因为它会与数组的文字语法冲突.
另一个众所周知的没有显式接收器就无法调用的方法示例是setters:
self.foo = bar # setter foo = bar # local variable
对于private
setter,实际上对private
方法规则有一个例外,它允许使用显式接收器调用它们,只要该显式接收器是文字伪变量关键字即可self
.但是,调用私有二元运算符或类似方法不存在此类异常[]
.(尽管有这样的建议.)