阿里云「飞天发布时刻」2024来啦!新产品、新特性、新能力、新方案,等你来探~ 了解详情
写点什么

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:114832
用户头像

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

关注

评论

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

祝大家元旦快乐,分享一些知识演讲

石云升

28天写作 12月日更

KubeEdge 王泽锋:只有代码没有生命力,凝聚开发者的社区才能活力无限Vol.8

OpenTEKr

大话开源

瞰见|从电厂螺蛳里看 Elastic 与亚马逊云的恩怨情仇

OpenTEKr

狄安瞰源

61 K8S之日志系统部署

穿过生命散发芬芳

k8s 28天写作 12月日更

Java 数据持久化系列之 HikariCP (一)

程序员历小冰

持久化 HikariCP 28天写作 12月日更

CentOS 停服,龙蜥社区已上线解决方案专区

OpenAnolis小助手

centos 国产操作系统 龙蜥社区

Postman 使用教程 - 手把手教你 API 接口测试

蒋川

Postman 接口测试

建木持续集成平台v2.1.1发布

Jianmu

DevOps CI/CD 开源软件

关于内核堆溢出漏洞的分析

网络安全学海

黑客 网络安全 信息安全 安全漏洞 渗透测试·

一个cpp协程库的前世今生(五)协程执行环境env

SkyFire

c++ cocpp

向未来飞驰:武汉推开了AI产业化和产业AI化的三重门

脑极体

五天玩转EMAS Serverless训练营

移动研发平台EMAS

阿里云 #Serverless #EMAS

seata分布式事务TCC模式介绍及推荐实践

恒生LIGHT云社区

分布式 分布式事务 seata TCC

最好的 6 个免费天气 API 接口对比测评

蒋川

API 天气api

盘点 2021|一个 SAP 成都研究院开发工程师的2021年度总结:既没有厚积,也未能薄发

Jerry Wang

程序员 28天写作 12月日更 盘点2021 盘点 2021

如何打造一个云原生背景下的可观测平台?

淡泊明志、宁静致远

一个cpp协程库的前世今生(四)协程上下文ctx

SkyFire

c++ cocpp

Hoo虎符研究院 | 币海寻珠最新一期的DAO生态

区块链前沿News

DAO Hoo 虎符交易所 虎符研究院

回顾 2021,拥抱 2022~

阿策小和尚

盘点2021

2022 让我们登上更大的舞台

坚果

28天写作 12月日更 2021年终总结 盘点 2021

如何将List<Integer>转换为int[]数组

liuzhen007

Java 28天写作 12月日更

当MySQL执行XA事务时遭遇崩溃,且看华为云如何保障数据一致性

华为云开发者联盟

MySQL 华为云

.NET6新东西--Logging Source Generator

喵叔

28天写作 12月日更

元宇宙很好,但VR开发者不准备停留在这里

脑极体

皮皮APP x 武汉市社会心理服务指导中心 联合开展社交讲座

联营汇聚

LabVIEW图像分割算法(基础篇—6)

不脱发的程序猿

机器视觉 图像处理 LabVIEW 图像分割算法

一个cpp协程库的前世今生(三)cocpp的核心框架结构

SkyFire

c++ cocpp

『征文精选』ShardingSphere-Proxy:Base 事务基于 Seata 验证

SphereEx

数据库 架构 开源社区 ShardingSphere SphereEx

瞰见|即将上市的云明星 HashiCorp 走过的开源之路

OpenTEKr

开源 狄安瞰源

瞰见 | 美股新贵Confluent背后的卡夫卡,不是那个魔幻小说家

OpenTEKr

狄安瞰源

VMware 任道远:中国的开源生态还处在萌芽发展的青春期,需要多元力量和全球化协作 I OpenTEKr 大话开源 Vol.9

OpenTEKr

大话开源

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