我正在设计我自己的编程语言(称为 Lima,如果你在 www.btetrud.com 上关心它),我正在努力思考如何实现运算符重载。我决定在特定对象上绑定(bind)运算符(它是一种基于原型(prototype)的语言)。 (它也是一种动态语言,其中 'var' 就像 javascript 中的 'var' - 一个可以保存任何类型值的变量)。
例如,这将是一个带有重新定义的 + 运算符的对象:
x =
{ int member
operator +
self int[b]:
ret b+self
int[a] self:
ret member+a
}
我希望它的作用相当明显。当 x 既是右操作数又是左操作数时,该运算符被定义(使用
self
表示这一点)。问题是当您有两个对象以像这样的开放式方式定义运算符时该怎么办。例如,在这种情况下您会做什么:
A =
{ int x
operator +
self var[b]:
ret x+b
}
B =
{ int x
operator +
var[a] self:
ret x+a
}
a+b ;; is a's or b's + operator used?
所以这个问题的一个简单答案是“好吧,不要做出模棱两可的定义”,但它并不是那么简单。如果您包含一个具有 A 类型对象的模块,然后定义了 B 类型对象怎么办。
您如何创建一种语言来防止其他对象劫持您想要对您的运算符(operator)执行的操作?
C++ 将运算符重载定义为类的“成员”。 C++ 如何处理这样的歧义?
最佳答案
大多数语言会优先考虑左边的类。我相信,C++ 根本不允许您重载右侧的运算符。当您定义 operator+
,当这种类型在左侧时,您正在定义加法,对于右侧的任何东西。
事实上,如果你允许你的 operator +
是没有意义的。当类型在右侧时工作。它适用于 +,但考虑 -。如果类型 A 定义 operator -
以某种方式,我做 int x - A y,我不想要 A 的 operator -
被调用,因为它会反向计算减法!
在 Python 中,它有更广泛的 operator overloading rules , 反方向有单独的方法。例如,有一个 __sub__
当此类型位于左侧时重载 - 运算符的方法,以及 __rsub__
当此类型位于右侧时,它会重载 - 运算符。这类似于在您的语言中允许“自我”出现在左侧或右侧的能力,但它会引入歧义。
Python 优先考虑左边的东西——这在动态语言中效果更好。如果 Python 遇到 x - y
,它首先调用x.__sub__(y)
看看 x
知道如何减去 y
.这可以产生一个结果,或者返回一个特殊值 NotImplemented
.如果 Python 发现 NotImplemented
被退回,然后尝试另一种方式。它调用 y.__rsub__(x)
,它会被编程知道 y
在右手边。如果这也返回 NotImplemented
,然后是 TypeError
引发,因为类型与该操作不兼容。
我认为这是动态语言的理想运算符重载策略。
编辑:稍微总结一下,你有一个模棱两可的情况,所以你真的只有三个选择:
唯一的其他选择是为运算符重载引入一个复杂的优先系统,但是你说你想减少认知开销。
关于overloading - 如何在编程语言中消除对象/类之间的运算符定义歧义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5320233/