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

2023-10-07 02:08

本文主要是介绍ClojureScript通过Javascript将Clojure引入到浏览器端,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 本文来源于我在InfoQ中文站翻译的文章,原文地址是:http://www.infoq.com/cn/news/2011/08/clojurescript

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

这篇关于ClojureScript通过Javascript将Clojure引入到浏览器端的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/155373

相关文章

分布式锁在Spring Boot应用中的实现过程

《分布式锁在SpringBoot应用中的实现过程》文章介绍在SpringBoot中通过自定义Lock注解、LockAspect切面和RedisLockUtils工具类实现分布式锁,确保多实例并发操作... 目录Lock注解LockASPect切面RedisLockUtils工具类总结在现代微服务架构中,分布

Java使用Thumbnailator库实现图片处理与压缩功能

《Java使用Thumbnailator库实现图片处理与压缩功能》Thumbnailator是高性能Java图像处理库,支持缩放、旋转、水印添加、裁剪及格式转换,提供易用API和性能优化,适合Web应... 目录1. 图片处理库Thumbnailator介绍2. 基本和指定大小图片缩放功能2.1 图片缩放的

Spring Boot集成/输出/日志级别控制/持久化开发实践

《SpringBoot集成/输出/日志级别控制/持久化开发实践》SpringBoot默认集成Logback,支持灵活日志级别配置(INFO/DEBUG等),输出包含时间戳、级别、类名等信息,并可通过... 目录一、日志概述1.1、Spring Boot日志简介1.2、日志框架与默认配置1.3、日志的核心作用

破茧 JDBC:MyBatis 在 Spring Boot 中的轻量实践指南

《破茧JDBC:MyBatis在SpringBoot中的轻量实践指南》MyBatis是持久层框架,简化JDBC开发,通过接口+XML/注解实现数据访问,动态代理生成实现类,支持增删改查及参数... 目录一、什么是 MyBATis二、 MyBatis 入门2.1、创建项目2.2、配置数据库连接字符串2.3、入

Springboot项目启动失败提示找不到dao类的解决

《Springboot项目启动失败提示找不到dao类的解决》SpringBoot启动失败,因ProductServiceImpl未正确注入ProductDao,原因:Dao未注册为Bean,解决:在启... 目录错误描述原因解决方法总结***************************APPLICA编

深度解析Spring Security 中的 SecurityFilterChain核心功能

《深度解析SpringSecurity中的SecurityFilterChain核心功能》SecurityFilterChain通过组件化配置、类型安全路径匹配、多链协同三大特性,重构了Spri... 目录Spring Security 中的SecurityFilterChain深度解析一、Security

SpringBoot多环境配置数据读取方式

《SpringBoot多环境配置数据读取方式》SpringBoot通过环境隔离机制,支持properties/yaml/yml多格式配置,结合@Value、Environment和@Configura... 目录一、多环境配置的核心思路二、3种配置文件格式详解2.1 properties格式(传统格式)1.

Apache Ignite 与 Spring Boot 集成详细指南

《ApacheIgnite与SpringBoot集成详细指南》ApacheIgnite官方指南详解如何通过SpringBootStarter扩展实现自动配置,支持厚/轻客户端模式,简化Ign... 目录 一、背景:为什么需要这个集成? 二、两种集成方式(对应两种客户端模型) 三、方式一:自动配置 Thick

Spring WebClient从入门到精通

《SpringWebClient从入门到精通》本文详解SpringWebClient非阻塞响应式特性及优势,涵盖核心API、实战应用与性能优化,对比RestTemplate,为微服务通信提供高效解决... 目录一、WebClient 概述1.1 为什么选择 WebClient?1.2 WebClient 与

Java.lang.InterruptedException被中止异常的原因及解决方案

《Java.lang.InterruptedException被中止异常的原因及解决方案》Java.lang.InterruptedException是线程被中断时抛出的异常,用于协作停止执行,常见于... 目录报错问题报错原因解决方法Java.lang.InterruptedException 是 Jav