QCon北京「鸿蒙专场」火热来袭!即刻报名,与创新同行~ 了解详情
写点什么

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

  • 2011-08-01
  • 本文字数:3109 字

    阅读完需:约 10 分钟

你可以通过 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

2011-08-01 02:114979
用户头像

发布了 88 篇内容, 共 266.0 次阅读, 收获喜欢 8 次。

关注

评论

发布
暂无评论
发现更多内容

第五周作业-流程图及时序图

Au revoir

网络编程入门从未如此简单(二):假如你来设计TCP协议,会怎么做?

JackJiang

TCP 网络编程

iOS开发前景

ios

LeetCode题解:152. 乘积最大子数组,动态规划,JavaScript,详细注释

Lee Chen

算法 大前端 LeetCode

神操作:就靠这份“Java核心技能精讲”,竟收割了22个Offer

比伯

Java 编程 架构 面试 计算机

Serverless 如何在阿里巴巴实现规模化落地?

Serverless Devs

阿里云 Serverless 云原生 大前端

细节完美炸裂!GtiHub上点赞已破百万的并发编程四套全彩手册

Java架构追梦

Java 阿里巴巴 架构 面试 并发

安卓软件开发文献!阿里P8架构师的Android大厂面试题总结,建议收藏

欢喜学安卓

android 程序员 面试 移动开发

连接AI与用户,京东云推出视音频通信技术方案

京东科技开发者

IoT 通信 视频会议

BML CodeLab发布重磅更新 一键配好Windows WSL2 AI开发环境

百度大脑

使用PG_STAT_REPLICATION监视复制

PostgreSQLChina

数据库 postgresql 开源 软件 开源社区

小程序开发-云开发技术总结

我是哪吒

小程序 程序员 大前端 28天写作 2月春节不断更

计算机视觉--opencv及paddlepaddle 环境安装

cloudcoder

bat文件调用cmd命令批量提取文件夹中的文件名(批量修改文件扩展名)

明金同学

Android NativeCrash 捕获与解析

vivo互联网技术

c++ android NativeCrash

Selenium 利用 JS/JQ 操作元素、鼠标键盘事件、Cookie 操作

梦想橡皮擦

Python 28天写作 2月春节不断更 selenium

MT马特量化机器人软件开发|MT马特量化机器人APP系统开发

系统开发

阿里中间件团队技术官手撸笔记,全新演绎“Kafka部署实战”,已开源

Java架构之路

Java 程序员 架构 面试 编程语言

资深大牛带你了解源码!分析Android未来几年的发展前景,快来收藏!

欢喜学安卓

android 程序员 面试 移动开发

程序员需要搞理财吗?

三石

理财 话题讨论

Agora 实时音视频调查工具水晶球

john

牛掰!面试不再慌,苦刷这份2020最全的“基础-中级-高级”面试题库,已涨17k

Java架构之路

Java 程序员 架构 面试 编程语言

一周信创舆情观察(2.8~2.21)

统小信uos

【死磕JVM】JVM快速入门之前戏篇

牧小农

跨平台 虚拟机 Java虚拟机 JVM虚拟机原理 hotspot

性能优化知多少

圣杰

sql 性能优化 dotnet

Flink 如何实时分析 Iceberg 数据湖的 CDC 数据

Apache Flink

flink

中小公司开展NPS的好处

狂补计算机基础知识,让我上了瘾

沉默王二

计算机基础 计算机

为了让你在“口袋奇兵”聊遍全球,Serverless 做了什么?

阿里巴巴云原生

云计算 Serverless 云原生 监控 调度

最新大厂Java面试题库,测试一下你能坚持到哪一面 “美团+字节+腾讯”三面技术问题

Java架构之路

Java 程序员 架构 面试 编程语言

MySQL索引原理,一篇从头到尾讲清楚

数据库 架构

ClojureScript通过Javascript将Clojure引入到浏览器端_Java_Werner Schuster_InfoQ精选文章