通过转换器在Javascript中实现运算符重载

时间:2011-09-18 18:03:22

标签: javascript coffeescript

对于我们中的一些人来说,使用Javascript的一个问题是缺少运算符重载。这使得编写数字库变得尴尬。例如,我们可能想写一些类似的东西:

var a = new BigInteger(5);
var b = new BigInteger(10);
var c = a + b;

一种可能的解决方案是通过运算符重载到Javascript来转换语言。虽然可行 - 通过函数调用和类型检查替换运算符 - 但似乎共识似乎是在不破坏性能的情况下这是不可能的。由于这个原因,CoffeeScript拒绝了这个想法:

https://github.com/jashkenas/coffee-script/issues/846

但是真的没有聪明的解决方案吗?

例如,可能有可能从紧密循环中提升类型检查或使用其他管道,现代JS编译器可以在类型为数字时优化远离添加的伪装。

想法?

2 个答案:

答案 0 :(得分:2)

你真的确定你需要用大数字编写正常数字的旧函数(使用传统的运算符)吗?如果您只是为了方便自己的功能需要重载,那么您可以通过使用不同的自定义运算符来控制您的bignums。

例如,您可以编写一个编译器来安全地转换

var d = a <+> b <*> c;

var d = (a).add((b).multiply(c));

或者,如果您想要自动转换......

var d = toBignum(a).add(toBignum(b).multiply(toBignum(c)));

我真的没有看到你能够在没有大麻烦的情况下强制重载现有的实现。虽然您可以使用&lt; +&gt;以teoretically替换所有出现的+。等等,目前的Javascript实现并未针对此进行优化,我甚至不想开始思考如果您尝试将bignum传递给其中一个本机C ++函数会发生什么。


编辑:不需要覆盖基本整数类是重要的一点(注意你给出的链接如何,覆盖是这个人想要的第一件事......)。我不认为你能找到某种“神奇”的优化,因为你无法控制客户使用多少JS实现中的哪一个。

如果您真的不喜欢像&lt; +&gt;这样的自定义运算符区分一个普通+操作符(你不应该干扰)和一个花哨的+操作符(你想做bignum的东西)的唯一方法是在Javascript之上强制某种特殊的打字系统,也许是通过评论,自定义语法或(如评论中所述)匈牙利表示法。只要找到一个自定义的运营商名称,你就不那么讨厌,IMO。

答案 1 :(得分:1)

看看Scala如何实现运算符重载:

他们定义每个运算符都是对象的方法调用,所以你的例子是:

var c = a["+"](b);

如果你在这里停止,你可以简单地实现方法重载,该函数必须检查param传递的值。如果你想开发一个更好的解决方案,请参阅Odersky的Scala编程书,并花一些时间阅读他们如何解决问题的所有想法(这是一个非常好的解决方案!)