原则上说,目前能看到的 Meta Programming 有两种,第一种专注于重新构成语法,即 DSL,Lisp/Scheme 属于此类,这几年的新科状元 Ruby 也属于这一派,甚至还有走得更远但相对小众的 REBOL Language;第二种专注于在编译期进行计算和分派以达到针对特定场景的自动代码选择优化,C++ 的模板属于此类。C 的宏则兼有两者,但能力都比较弱。据我见过的情况,学院派的比较认可前一种,后一种则借 C++ 的东风用得更广泛。

问题引言里的那句话,我认为是在说 C++,因为它强调了 do part of the work at compile time。但 Python 的 Meta-programming,我闻所未闻。Python 1.2 开始用到现在,我确实没有听说 Python 有什么构建 DSL 的能力,更遑论所谓 Meta-programming。Python 社区的文化,也向来没有在语法上玩花样的传统。于是大略查了查,它说的是应该是第三项东西:类结构动态调整,本质来说,就是反射(reflection)。参照 DeveloperWorks 上的这一篇:Metaclass programming in Python,以及这一篇:Metaprogramming。不难看出,这两篇文章谈的是完全另一个话题。因此谈所谓 Lisp 和 Ruby 在 Meta-programming 上为什么比 Python 做得好,在我看来是一个伪命题,因为两者说的 Meta-programming 的内涵和外延都不一样。

在实际工作中,无论哪一种 Meta-programming,我都持否定态度。但理由和前面朋友的观点不同。我认为 Meta-programming 破坏了交流中的一项基本原则:同样的编程语言,应当有同样的交流习惯。过于随意地构造 DSL,让程序员之间的交流变得更加困难。这一方面的典型例子是 REBOL,几种 DSL 语法差异明显,重新学习的成本过高,也实际上助长了社区的分裂倾向。闲来无事,自己玩玩也就算了;放在工作里,害人害己。

至于 Lisp/Scheme 家族的 Meta Programming,与其说是做得更好,倒不如说是语法结构过于简单导致其怎么变换都是长得一个样子。关于这一点,不妨对比一下 REBOL,它构造出来的几个 DSL 语法上没有多少相似之处。不过,对我来说,Lisp/Scheme 这种语法简单其实才是我喜欢的 Scheme:编译器的设计者可以把更多的精力花在运行时和优化上。

还是那句话,我们写程序是为了解决问题。抽象和表达方式是手段,不是目的。汲汲于语法上的花头,是耍滑头。

— 完 —

本文作者:陈甫鸼

【知乎日报】
你都看到这啦,快来点我嘛 Σ(▼□▼メ)

此问题还有 13 个回答,查看全部。
延伸阅读:
什么是 Monad (Functional Programming)?
C++ Primer与C++ 大学教程(C++ How to Programming)哪个更好些,应当选择怎样的教材?

分享到