BT

ClojureScript通过Javascript将Clojure引入到浏览器端

作者 Werner Schuster ,译者 张龙 发布于 2011年8月1日 | 被首富的“一个亿”刷屏?不如定个小目标,先把握住QCon上海的优惠吧!

你可以通过ClojureScript使用Clojure语言编写代码,然后将其编译为Javascript。ClojureScript是由Clojure的创建者Rich Hickey发布的(这里是Rich的ClojureScript声明ClojureScript声明的视频)。

ClojureScript是Clojure的一个子集,目前缺失的特性与库要么是尚未实现,要么是由于对Javascript VM毫无意义而不会添加进来,比如线程支持、Java集成等等。ClojureScript Wiki上详细列出了Clojure与ClojureScript之间的差异列表

设计ClojureScript的缘由

ClojureScript的基本原理(摘录自文档)就是“做Javascript所能做到的事情”。Javascript VM正变得越来越快,应用的领域也越来越广。借助于ClojureScript,我们可以将Clojure用于GUI客户端编程、包括移动平台(带有强大的HTML组件与Javascript VM)。运行Clojure需要客户端安装有Java VM;虽然桌面操作系统可能都有Java VM,但浏览器的应用却更加普遍,并且每个客户端操作系统都会有浏览器。这种局面在移动平台上就更清晰了——目前还没有哪个主流的移动平台带有可以直接运行Clojure的Java VM。Android并不带Java VM;它需要将所有字节码转换为Dalvik VM字节码;现在人们还在为能让Clojure顺利运行在Android上而不断努力

ClojureScript还有另一个使用场景:命令行程序。Java的命令行程序使用的并不多,特别是需要频繁加载的程序,原因在于JVM的启动时间(诸如Nailgun之类的解决方案就是为了解决这个问题而出现的)。正如Rich Hickey所述,如果将命令行程序编译为Javascript,然后使用Node.js运行会大大降低启动时间。

关于在服务器端使用Javascript的一个普遍观点是可以在服务器端和客户端重用相同的代码;特别是像输入验证这样的逻辑。借助于ClojureScript依然可以做到这一点:使用ClojureScript编写的算法可以编译为Javascript并运行在浏览器中,同时还可以用在服务器端的Clojure代码基中,这时算法会被编译为Java字节码。它还为在服务器端完全抛弃Java提供了一种可能——使用ClojureScript编写应用,然后在Javascript栈如Node.js上运行服务器端。

ClojureScript的实现方式

ClojureScript编译器并没有任何Javascript代码,它使用Clojure编写,这意味着编译器需要运行在Java VM上。因此,ClojureScript缺少eval和其他类型的运行时代码加载能力。ClojureScript的目的在于编写程序并将其编译为Javascript而非作为浏览器中的REPL。

然而,确实有ClojureScript REPL,它位于ClojureScript仓库中,使用Clojure实现,它用于启动Rhino——使用Java编写的Javascript运行时。要想运行ClojureScript代码,需要将其发送给基于Clojure的ClojureScript编译器,后者会返回Javascript代码,然后由Rhino运行。在浏览器中不通过Clojure实例来这么做显然是不可行的——至少需要将Clojure编译器工具链编译成Javascript才行。

ClojureScript代码可以使用Clojure宏。宏是个编译期的特性;如果ClojureScript代码引用了宏调用,那么宏扩展就会被ClojureScript编译器所执行,在Clojure中执行。

虽然目前ClojureScript编译器只能运行在Clojure上,但ClojureScript却带有Clojure Reader。说明一下,Reader基本上是个Clojure解析器;它会将文本形式的Clojure程序转换为Clojure数据结构,然后再对该数据结构求值。ClojureScript自带的Reader可以解析Clojure(Script)符号中的数据,然后以数据的形式将其传递给ClojureScript代码。ClojureScript的Reader只会解析,由于运行期并没有ClojureScript编译器,因此它并不会求值。

ClojureScript之所以带有Reader的目的在于读取Clojure数据,就像Javascript无需求值就可以读取JSON数据一样。我们可以通过Clojure生成Clojure数据并将其发送给ClojureScript,反之亦然。

事实上,ClojureScript编译器工具链的另一部分是Google Closure工具集。没错,带有字母“s”的Closure,他们的命名很像,但Google的Javascript工具Closure集合,特别是Closure编译器和Advanced Compilation都用到了。

Closure可用于几个目的:其中一个目的就是库与依赖的管理,这需要库与导出符号。ClojureScript命名空间定义与Google Closure的provide与require调用对应。这样,ClojureScript就可以轻松使用Google Closure库了,该库拥有非常丰富的GUI组件和其他特性。

ClojureScript与Clojure语言非常像,但其标准库是Clojure的一个子集。目前,ClojureScript的标准库有clojure.string、clojure.set、clojure.walk、clojure.zip等,同时更多的库将会被添加进来。将Clojure库移植到ClojureScript的难度取决于代码本身;仅使用基本语言元素来转换数据的纯算法代码很容易移植。使用了I/O库、线程、特定Java库的库则需要更多的工作;我们还需要分解平台特定的代码,这都是必要的工作。

Google Closure一个有趣的用法就是作为优化编译器的后端。ClojureScript编译器所生成的代码会进行优化以便与Closure的Advanced Compilation协同工作,它会接收Javascript源代码并对其进行优化,包括内联的函数调用、删除死代码(dead code)与无用的函数。这种方式的一个优势在于ClojureScript编译器无需实现这些优化工作了;它只需将其委托给Google Closure即可。

未来,其他的工作也可以委托给Google Closure,比如为调试器提供源代码图,也就是说数据结构可以匹配生成的Javascript代码和生成它的ClojureScript代码。Google Closure对SourceMaps提供了一定的支持,同时Mozilla与WebKit项目都在致力于扩展其浏览器、调试器和Javascript引擎来支持他们。

不久大家就会看到关于ClojureScript的更多信息;其中一个信息来源就是Michael Fogus的博客,他已经发布了关于编译器系列文章的第一部分。Michael从事于ClojureScript实现。对编译器内部机制感兴趣的开发者们还应该看看ClojureScript开发说明,上面列出了很多信息,比如ClojureScript语言结构及其转换而成的Javascript结构。

Clojure社区已经开始尝试ClojureScript了。Brian McKenna已经开始尝试使用宏来与回调地狱(callback hell)展开斗争,这指的是异步I/O的每个操作都需要提供一个回调来接收操作的结果——这么做一两次还行,但对于连续的算法来说实在过于冗长了。在JS世界中有不少解决方案在尝试解决这个问题,从新的语言如StratifiedJS使用Javascript编写的嵌入式DSL库

Brian混合使用了嵌入式DSL解决方案与ClojureScript,就像是带有宏的LISP一样,效果不错。试验处理了一系列的表达式并将其编译为嵌套的回调,每个回调都在序列中执行一个表达式,然后通过setTimeout调度序列中其他回调的执行。这不禁让人想起了支持Monads(Haskell的do符号)的语言或是F#的Compuational Expressions(Async Workflows)的程序分号方式。接下来将会支持更多的结构化程序设计概念,如循环,使用宏将其转换为这种连续的传递形式。

Justin Grant的一篇博文介绍了如何实现一个算法并使用Google Closure的Canvas支持来绘制图像

ClojureScript位于GitHub。要想了解更多信息,请查看clojure.com上的ClojureScript声明,或是GitHub上的ClojureScript Wiki,上面有大量的信息,包括ClojureScript的基本原理快速起步指南等内容。Clojure邮件列表也是个不错的信息来源,你可以从中了解到ClojureScript的使用方式,社区也在上面讨论开发工作流、工具等信息。

查看英文原文:ClojureScript Brings Clojure To The Browser via Javascript

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

ClojureScript + Nodejs = 王者组合 by 曹 云飞

server端Javascript势头越来越强,快成气候了

Re: ClojureScript + Nodejs = 王者组合 by wang metis

server端Javascript势头越来越强,快成气候了

为什么不是clojure+clojurescript

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

2 讨论
提供反馈
错误报告
商务合作
内容合作
Marketing
InfoQ.com及所有内容,版权所有 © 2006-2016 C4Media Inc. InfoQ.com 服务器由 Contegix提供, 我们最信赖的ISP伙伴。
北京创新网媒广告有限公司 京ICP备09022563号-7 隐私政策
BT

We notice you’re using an ad blocker

We understand why you use ad blockers. However to keep InfoQ free we need your support. InfoQ will not provide your data to third parties without individual opt-in consent. We only work with advertisers relevant to our readers. Please consider whitelisting us.