ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

谁家的重载更强?proposal-operator-overloading 对比 Python/C++/Haskell/Matlab 运算符方案

谁家的重载更强?proposal-operator-overloading 对比 Python/C++/Haskell/Matlab 运算符方案 谁家的重载更强proposal-operator-overloading 对比 Python/C/Haskell/Matlab 运算符方案【免费下载链接】proposal-operator-overloading项目地址: https://gitcode.com/gh_mirrors/pr/proposal-operator-overloading运算符重载Operator Overloading是编程语言设计中最具争议的话题之一。proposal-operator-overloading 是一份曾提交给 TC39JavaScript 标准委员会的著名提案它试图让 JavaScript 开发者能用、*、等原生运算符直接操作 Decimal、向量、矩阵等自定义类型。提案虽然最终被撤回但它附带的跨语言对比文档LANGCOMP.md系统梳理了 Python、C、Haskell、Matlab 等主流语言的运算符方案。本文用最通俗的方式带你看懂这五种方案各自的强项与短板以及 JavaScript 真正需要的是哪种重载。为什么 JavaScript 需要运算符重载JavaScript 传统上只有 Number 和 BigInt 两种数值类型而开发者实际需要十进制小数、复数、有理数、向量、矩阵等更多类型数值类型扩展Decimal(1) Decimal(2)直接得到Decimal(3)而不是调用一堆方法向量与矩阵运算new Vector([1,2,3]) new Vector([4,5,6])这种自然写法公式 DSLTensorFlow.js 中a * x ** 3 b * x ** 2 c * x d比.mul().add()方法链直观得多CSS 单位计算Css.em(3) CSS.px(2)让前端样式计算更顺手提案在README.md中给出了这四个典型案例核心诉求只有一个让数学表达回归数学本身。proposal-operator-overloading 项目速览 ⚡提案作者Daniel EhrenbergTC39 核心成员littledan当前状态Withdrawn已撤回项目结构LANGCOMP.md跨语言运算符方案对比本文的主要素材PROTOSPEC.md底层规范草案src/transform/Babel 插件实现plugin.jssrc/shim/运行时支持shim.js提案提出了三个设计目标表现力Expressivity、可预测性Predictability、可高效实现Efficiently implementable。这三个词也正好是评判下文五种方案的标尺。一张表看懂五种运算符方案 语言/方案重载哪些运算符分发机制能否自定义运算符优先级Python内置运算符先查左操作数再查右操作数否固定C内置运算符编译期静态分发否固定Haskell内置运算符类型类Type Class单分发能可自定义优先级用户定义Matlab内置运算符按操作数优先级分发否固定JS 提案内置运算符基于左右操作数的双分发否固定可以看出大部分主流语言都选择了只重载内置运算符的保守路线——只有 Haskell 敢把自定义运算符和优先级完全交给用户。Python 方案双下划线方法的优雅与代价 Python 是运算符重载做得最顺手的语言靠的是一组魔术方法__add__、__sub__、__mul__定义二元运算__radd__处理左操作数是内置类型的情况如3 * vector先查左操作数的__add__找不到再查右操作数的__radd__这就是 Python 的分发逻辑。NumPy 把这种能力用到了极致也让 Python 成为数据科学领域的第一语言。但LANGCOMP.md也指出了两个缺点一是左侧优先两个自定义类型相遇时行为不够对称二是每次运算都要做两次属性查找性能开销不小。C 方案静态分发的高性能 C 用operator关键字把运算符当作函数重载在编译期就确定调用哪个版本运行时零开销这是它性能最强的根本原因。不过 C 也是运算符滥用的重灾区——LANGCOMP.md直言C 和 Haskell 经常因为过度使用晦涩运算符而被批评可读性差。重载是利器但用不好就会变成代码里的天书。Haskell 方案类型类与自定义优先级 Haskell 把运算符定义在类型类如 Num中通过类型系统完成单分发逻辑非常严谨。它还允许用户自定义运算符甚至自定义优先级与结合性infixl / infixr。听上去很自由但代价巨大为了解析一段代码编译器必须导入其他模块的优先级声明LANGCOMP.md称之为反模块化问题实际实现中有时需要多遍遍历模块图才能完成解析。这也是 JS 提案明确拒绝自定义运算符的原因。Matlab 方案操作数优先级分发 Matlab 的分发逻辑别具一格通过 InferiorClasses 属性标记操作数的优先级运算时调用优先级更高的操作数上的方法。有趣的是LANGCOMP.md明确指出这份 JS 提案的分发方式与 Matlab最相似——基于两个操作数的 Operator Set 进行双分发而不是像 Python 那样左侧优先。这种方式能保证左右操作数地位对等更符合数学直觉。JS 提案的独特设计重载也要讲规矩 ✅proposal-operator-overloading 除了借鉴各语言经验还有三个独门设计显式开启用with operators from声明开启重载避免不经意间改变已有代码行为只重载内置运算符 - * / % **、位运算、与等比较运算、、||、.、函数调用等一律不允许重载派生运算符、、由派生由派生大幅减少重复定义规范细节见PROTOSPEC.md而src/transform/plugin.js和src/shim/shim.js给出了 Babel 插件的完整参考实现。谁家的重载更强最终结论 论优雅Python 胜NumPy 证明运算符重载能让代码显著更整洁论性能C 胜编译期静态分发实现零运行时开销论自由Haskell 胜但自由的代价是解析复杂度和可读性论平衡Matlab 与 JS 提案胜双操作数分发最符合数学直觉回到标题的问题其实没有绝对的最强。proposal-operator-overloading 的价值在于它把各语言的优点和踩过的坑都摆在了桌面上让 JavaScript 的每一次语法演进都有据可依。对普通开发者来说理解这几种方案也等于掌握了阅读任何语言运算符语义的通用钥匙。想亲手体验三步跑通 Babel 插件 虽然提案已撤回但你可以用配套的 Babel 插件提前体验重载手感npm install --save-dev littledan/plugin-transform-operator-overloading npm install --save-prod littledan/operator-overloading-shim然后在.babelrc中启用插件{ plugins: [littledan/plugin-transform-operator-overloading] }注意Babel 插件版本用withOperatorsFrom()替代提案语法with operators from并建议只在需要的代码块内开启完整说明见src/transform/README.md。想直接看源码克隆仓库即可git clone https://gitcode.com/gh_mirrors/pr/proposal-operator-overloading结语 运算符重载不是新概念但 JavaScript 能否承载它一直是个开放问题。proposal-operator-overloading 用一份扎实的跨语言调研LANGCOMP.md给出了自己的答案保守、可预测、尊重数学直觉。无论这份提案最终去向如何它留下的对比资料都是理解运算符重载的最佳入门读物。【免费下载链接】proposal-operator-overloading项目地址: https://gitcode.com/gh_mirrors/pr/proposal-operator-overloading创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表