你不能比较语言特性,只能比较语言
英文原文:You can’t compare language features, only languages
译/腊八粥
很多编程语言的争论方式是“X特性真的不错,每种语言都需要它”,或“X特性比与之相对的Y特性要好很多”。经典例子是静态 VS 动态类型,不过还有很多例子,比如元编程的不同类型等。
我经常发现自己被扯在这些辩论中的不同方向,因为我对 Haskell 和 Python 稍微有些不公平了。但是我想提议的是,做这种抽象的比较、而没有基于具体的语言,是一种误导,原因如下:
就我的经验看,Haskell 里的静态类型与C的静态类型几乎完全不同,与C#1.0 就更不同了,据我所知,与C#5.0 的静态类型更加不一样。把这些静态类型混在一起真的有意义吗?
类似地,Shell 脚本、PHP、Python 和 Lisp 里的动态类型或许比它们本来的样子更加不同。你甚至不能把它们放在一个范围内——例如,与 PHP 相比,Python 不是简单的‘强’类型系统(不能把字符串转换成数字等),因为它也有支撑更大灵活性和威力(比如基于第一类对象的动态子集)的特性。
特性组合是无关紧要的
比如,我最喜欢的 Python 特性之一是关键字参数。它们经常增加调用代码的清晰度,以向后兼容方式给函数增加新特性的功能。然而,这些特性只有在和其它特性组合时才有意义。如果你有 关键字参数、而没有传递或接受关键字参数未知集合的**kwargs 语法,那么这将让 decorator 变得非常难。
如果你正在思考 Python 有多么优秀,那么我不认为它对你把总的关键字参数做为杀手级特性去谈论有多少帮助。它是在 Python 里运行尤其良好的关键字参数。
比较语言特性给不好的争论带来了很多机会
例如:
攻击最糟糕的实现
动态类型支持者可能说,静态类型意味着相对于指示类型(indicate type)太过重复和冗长呆板。这种批评可能应用到 Java,但是它不好应用到 Haskell 和很多其它的现代语言,在你可能需要定义类型的地方,类型推理(type inference)处理了 95% 的情况。
保护最好的实现
上面谬论的结果就是,如果你仅仅抽象地辩论语言特性,你就能随便找到你想要的实现来驳斥某个观点。有人宣称动态类型给 IDE 支持重构增加了难度,动态类型支持者会以“Smalltalk 不存在这种情况”为反驳——忽略了他们从来不用 Smalltalk 的事实,他们从来没有用过 Smalltalk,他们选择的动态类型语言真的表现更好,甚至存在自动化重构上不可解决的问题。
保护假设的实现
保护最好的实现走得更远,而你实际上在保护着还不存在的实现。
虚构的“足够聪明的编译器”就是个例子,另一个例子就是动态类型支持者可能谈论的“改进”动态分析。
假设的实现对于赢取辩论总是有好处的,尤其是在他们组合了所有语言的所有最好特性的时候,而没有担心这些特性将真正适合放在一起,并生成人们真正想用的功能。有时候这种混合产物就像 Hercules,有时候却像非洲蜂。
忽视其它
在选择编程语言时,不只是你不得不考虑语言特性——还有其它一长串因素,比如语言的成熟度、社区、资源库、文档、工具、程序员的数量(和质量)等。
有时候这些因素的质量受到历史事件(哪种语言、什么时候流行了)的控制,有时候它们可被追溯到语言设计的特性上。
很多语言战争的争论都忽略了所有这些因素。不过更容易出现的是,你是否实际地比较了真正的语言——只是其它方面抽象出来的语言特性。
我明白,一下子比较每个方面是困难的,我们总是试图把事物分解来分析。但是我怀疑,这将离编程语言很远很远,因为不同特性彼此交互的方式,还有对其它所有东东发展的方式产生巨大的影响,比如资源库。
结论
语言特性存在于语言环境和语言周围所有因素里。对我而言,在环境外面分析它们的企图将容易导致错误的概括。
当然,真正具体地、谈论具体语言经常导致更多有其自身陷阱的个人因素!有一种不错的方法吗?
原文地址:http://lukeplant.me.uk/blog/posts/you-cant-compare-language-features-only-languages/