写点什么

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

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

关注

评论

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

oracle已有表的分表分区优化操作步骤(单表过大)

zhengzai7

oracle 表分区

Golang微服框架Kratos与它的小伙伴系列 - ORM框架 - Ent

golang ORM Kratos

Golang微服务框架kratos实现SignalR服务

golang SignalR Kratos

Golang微服务框架kratos实现Socket.IO服务

golang socket websocket Kratos

直播程序源码开发建设:洞察全局,数据统计与分析功能-山东布谷科技创作

山东布谷科技

软件开发 直播 源码搭建 程序源码 mac数据分析统计软件

视觉套件专项活动!与飞桨技术专家一起提升技术实力,更多荣誉奖励等你领取

飞桨PaddlePaddle

人工智能 百度 paddle 飞桨 百度飞桨

Java基础 日期和时间

java易二三

程序员 计算机 java 编程

拥抱AIGC,他们有话说——百度李双龙:AIGC将赋能多个场域并惠及千行百业

百度Geek说

人工智能 百度 企业号 7 月 PK 榜 AICG

3D建模和3D渲染是吃CPU还是显卡?以及专业图形显卡和游戏显卡的区别

Finovy Cloud

3D

快速玩转 Llama2!阿里云机器学习 PAI 推出最佳实践(二)——全参数微调训练

阿里云大数据AI技术

人工智能

fastposter v2.16.0 让海报开发更简单

物有本末

图片处理 海报生成器 海报生成

Golang微服务框架kratos实现SSE服务

golang websocket Kratos openai

Golang微服务框架Kratos实现GraphQL服务

golang graphql Kratos

Golang微服务框架Kratos实现Thrift服务

Dify.AI:简单易用的 LLMOps 平台,可视化创造和运营你的 AI 原生应用

Dify

AI LLMOps

Cassandra SSTable 合并策略(一):STCS

冰心的小屋

Cassandra STCS Compaction

热烈祝贺埃文科技荣获CCF第38届中国计算机应用大会计算机应用科学技术二等奖

郑州埃文科技

Kratos 大乱炖 —— 整合其他Web框架:Gin、FastHttp、Hertz

golang gin Kratos

澜舟科技创始人兼CEO周明受邀出席“基础科学与人工智能论坛”

澜舟孟子开源社区

百度智能云连拿四年第一,为什么要深耕AI公有云市场

脑极体

AI 大模型

Java程序员常用的日志框架有哪些?

java易二三

Java 编程 程序员 计算机

分布式事务两阶段提交和三阶段提交有什么区别?

王磊

java面试

Golang微服框架Kratos与它的小伙伴系列 - ORM框架 - GORM

golang ORM gorm Kratos

用故事给予企业全面预算管理一个灵魂

智达方通

全面预算管理 企业全面预算管理 预算场景

密集发布AI应用后,微软2023财报传递了什么信号|TE解读

TE智库

Spring AOP 中,切点有多少种定义方式?

江南一点雨

Java spring

指标让 AI 更懂业务|Kyligence Copilot 是如何做到的?

Kyligence

Kyligence Copilot 数智助理

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