转载

JavaScript 玩转 Clojure 大法之 Macro(一)

我非常不喜欢中文字面翻译–'宏', 中文宏的意思是大, 广大, 实在想不通这跟macro有毛关系. 而macro值的是某条指令可以扩展 成一堆其它指令. 反而用个图我觉得更贴切

JavaScript 玩转 Clojure 大法之 Macro(一)

(macroexpand '(when-not (= 1 3) (print "damn"))) ; => (if (= 1 3) nil (do (print "damn")))

看看Clojure的macro when-not 能扩展成什么? 神奇的变成了if.

靠, 这不是就是语法糖?

嗯, 就是语法糖, 但是是强大的可以自定义的语法糖. 这代表着你可以用Clojure编写自己独特版本的Clojure.

lisp语言因为本身的原因能轻松这么办到

  • 语法简单,只有s-expression
  • 数据即代码, s-expression本身就是树形数据结构
  • lexer(词法分析器) → Reader → expander

如果英文好, 可以看看 这篇解释clojure macro的文章

但是就算可以自定义语法糖, 到底有什么好处呢, 真的只是使语法更好看吗?

当然不是, macro可以说是元编程的终极形态, 当Clojure推出core.async这么牛逼的库之后, 立即就被port到 ClojureScript, 也就是说, ClojureScript写的 go block 可以编译成能在浏览器上抛的单线程JavaScript.

如果回忆不起来可以翻看下如何用JavaScript实现 core.async 的 go block. 你会发现 generator 是实现的关键, 而ClojureScript却只用macro展成不同的纯状态机实现.

怎么做到的呢, 就是macro, 如果你翻看ClojureScript 的 core.async源码 , 会看见一堆一堆的macro. 根据go block 中不同的语法扩展成不一样的状态机.

正文到此结束
Loading...