不要轻易使用元编程

栏目: Lisp · 发布时间: 1年前

来源: lotabout.me

本文转载自:http://lotabout.me/2018/think-twice-before-utilizing-meta-programming/,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有。

元编程就像核弹,自己梦寐以求,却不希望别人拥有。

一般说元编程分为两类,一类是宏,在编译时期生成代码;另一类是运行时修改代码的行为。而不论是哪一类,我的建议是在决定使用之前要慎重考虑。元编程能让我们扩展语言本身,是十足的黑魔法;但用好不易,容易造成团队/社区在意见是实现上的分裂。(另外这篇文章里主要是对元编程的一些吐糟,并不包含基础知识的介绍。)

光明与黑暗

一上来,我们先看 Common Lisp 里的 loop 宏就。一方面,它体现了宏的强大;另一方面,它展现了宏能给我们带来的复杂。

熟悉 C/Java 语言都知道循环是语言本身提供的关键字,一般是 for 。但 Lisp 语言特别精简,它认为循环只是递归的一个特殊形式,语言本身也不包含任何的循环关键字。于是有人用宏实现了 loop ,它让我们能以近乎英语的方式在 Lisp 里写循环语句,这里从 这里 摘抄一个例子:

(loop for x in '(a b c d e)
      for y from 1

      if (> y 1)
      do (format t ", ~A" x)
      else do (format t "~A" x)
      )

你不需要了解这段代码的含义,重要的是了解像 for .. in .. , if ... do ... else ... do 这样的语法并不是 Lisp 提供的,而是 loop 宏实现的,这些语法离开了 loop 也就不再合法。

我们看到 loop 宏让我们能在 Lisp 语言不支持的情况下享受到近乎现代语言中才包含的 for ... in ... 语法。要知道在 Java 中有两种 for 语句:

for (int i=0; i < array.length; i++) {
    System.out.println("Element: " + array[i]);
}

for (String element : array) {
    System.out.println("Element: " + element);
}

而第二种直到 JDK 1.5 才加入。在这之前,广大的 Java 程序员即使已经认识到了第二种写法的优越性,却也只能无奈等到语言支持才行。而 Lisp 程序员很快就能通过宏来实现自己理想中的语法。

然而光明与黑暗共生,宏给我们带来极大自由的同时,也意味着分裂。每个 程序员 心中理想的语法各不相同,这就意味着一千个程序员会有一千种语法。在 Lisp 中宏是非常容易编写的(不代表容易正确编写),意味着真的会存在一千种语法,大家谁也不服谁,因此造成分裂;但在 C/Java 中,没有宏的支持,虽然有一千种想法,但大家都写不出编译器,于是只能集中讨论,统一语法了,再靠大牛们实现了。

而现实就是如此,Common Lisp 尝试标准化 Lisp,但依旧有人不认同这种理念,例如 Scheme,Common Lisp 标准化的 loop 宏在 Scheme 中就被抛弃了。

照进现实

前车之鉴,后事之师。Lisp 强大的功能,反面导致了语言的分裂,最终使 Lisp 也慢慢退出历史舞台(主流地位),这也被称为 The Lisp Curse 。而现实中我们也常常会被元编程的强大和便捷诱惑,我认为使用元编程之前最好考虑会不会造成更多的分裂。最基本的就是不应该自己造语法(DSL)。

当然,我的出发点是多人团队,较大的项目,考虑的是整体的发展。如果是个人学习,或者小团队等,元编程或许能成为你出众的秘密武器。但大的项目讲求的是合作,DSL 造成的分裂实在是得不偿失,尤其是作者离开后,维护的工作经常后继无人。

近两年接触到的 rust 也是提供了宏的支持,虽然不像 Lisp 宏一样容易编写,但从功能的角度上依旧特别强大,而且模板宏写起来也很容易,于是有人想写一个类似 Pythondict 语法

let x = dict!(
    "hello" => "world"
    ,"hello2" => "world2"
);

但我个人并不喜欢这种语法,我认为 Clojure 似的语法更简洁 dict!("hello": "world") 。那在团队里引入这两个宏就会引起代码的分裂,后来人在看代码时就会很困惑。不利于团队的建设。

最后分享在 知乎 上看到的引用:

Hygienic Macros and Compile-Time Evaluation: A first-class macro system, or support for compile-time code execution in general, is something we may consider in future releases. We don’t want the existence of a macro system to be a workaround that reduces the incentive for making the core language great.

Swift 表示不希望用宏来解决语言本身的缺陷。

而我的理解是当我们希望用宏(或其它元编程手段)时,很可能是我们使用的语言缺少了某些特性,例如 Java 的 lombok 提供的 @Getter/@Setter 等注解,就是因为 Java 没有相应的语言层面的支持,看看 Kotlin 的支持你就会明白的。

但即便有了宏(或元编程)的支持,你有信心能做出让整个团队都信服的设计吗?如果没有,最好还是慎重为之。

写在最后

虽然是吐糟,但这篇之间重写了三次。想表达的内容很多,最终还是把其它的东西删去, Lisp curse 还是我想真正表达的东西吧,其它的基础知识,有缘人自然会从其它地方学会。

年轻人容易崇拜力量,我们也别忘了阳光还有影子。


以上所述就是小编给大家介绍的《不要轻易使用元编程》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

关注码农网公众号

关注我们,获取更多IT资讯^_^


为你推荐:

相关软件推荐:

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

IT不再重要

IT不再重要

(美)尼古拉斯·卡尔 / 闫鲜宁 / 中信出版社 / 2008-10 / 29.00元

在这部跨越历史、经济和技术领域的著作中,作者从廉价的电力运营方式对社会变革的深刻影响延伸到互联网对我们生活的这个世界的重构性影响。他批判式的认为,企业想应用网络或应用程序,不再需要自建资料中心、自组IT团队维护和管理系统,因为互联网就像自来水或电力一样,可由专门公司提供服务,你可以付费使用。而如果他的设想真的会实现,我们的世界将会变成什么样子?IT产业的命运又将如何?这又对企业的IT领域投资产生什......一起来看看 《IT不再重要》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具