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

相关文章

在React中引入Tailwind CSS的完整指南

《在React中引入TailwindCSS的完整指南》在现代前端开发中,使用UI库可以显著提高开发效率,TailwindCSS是一个功能类优先的CSS框架,本文将详细介绍如何在Reac... 目录前言一、Tailwind css 简介二、创建 React 项目使用 Create React App 创建项目

Java编译生成多个.class文件的原理和作用

《Java编译生成多个.class文件的原理和作用》作为一名经验丰富的开发者,在Java项目中执行编译后,可能会发现一个.java源文件有时会产生多个.class文件,从技术实现层面详细剖析这一现象... 目录一、内部类机制与.class文件生成成员内部类(常规内部类)局部内部类(方法内部类)匿名内部类二、

SpringBoot实现数据库读写分离的3种方法小结

《SpringBoot实现数据库读写分离的3种方法小结》为了提高系统的读写性能和可用性,读写分离是一种经典的数据库架构模式,在SpringBoot应用中,有多种方式可以实现数据库读写分离,本文将介绍三... 目录一、数据库读写分离概述二、方案一:基于AbstractRoutingDataSource实现动态

Springboot @Autowired和@Resource的区别解析

《Springboot@Autowired和@Resource的区别解析》@Resource是JDK提供的注解,只是Spring在实现上提供了这个注解的功能支持,本文给大家介绍Springboot@... 目录【一】定义【1】@Autowired【2】@Resource【二】区别【1】包含的属性不同【2】@

springboot循环依赖问题案例代码及解决办法

《springboot循环依赖问题案例代码及解决办法》在SpringBoot中,如果两个或多个Bean之间存在循环依赖(即BeanA依赖BeanB,而BeanB又依赖BeanA),会导致Spring的... 目录1. 什么是循环依赖?2. 循环依赖的场景案例3. 解决循环依赖的常见方法方法 1:使用 @La

Java枚举类实现Key-Value映射的多种实现方式

《Java枚举类实现Key-Value映射的多种实现方式》在Java开发中,枚举(Enum)是一种特殊的类,本文将详细介绍Java枚举类实现key-value映射的多种方式,有需要的小伙伴可以根据需要... 目录前言一、基础实现方式1.1 为枚举添加属性和构造方法二、http://www.cppcns.co

Elasticsearch 在 Java 中的使用教程

《Elasticsearch在Java中的使用教程》Elasticsearch是一个分布式搜索和分析引擎,基于ApacheLucene构建,能够实现实时数据的存储、搜索、和分析,它广泛应用于全文... 目录1. Elasticsearch 简介2. 环境准备2.1 安装 Elasticsearch2.2 J

Java中的String.valueOf()和toString()方法区别小结

《Java中的String.valueOf()和toString()方法区别小结》字符串操作是开发者日常编程任务中不可或缺的一部分,转换为字符串是一种常见需求,其中最常见的就是String.value... 目录String.valueOf()方法方法定义方法实现使用示例使用场景toString()方法方法

Java中List的contains()方法的使用小结

《Java中List的contains()方法的使用小结》List的contains()方法用于检查列表中是否包含指定的元素,借助equals()方法进行判断,下面就来介绍Java中List的c... 目录详细展开1. 方法签名2. 工作原理3. 使用示例4. 注意事项总结结论:List 的 contain

Java实现文件图片的预览和下载功能

《Java实现文件图片的预览和下载功能》这篇文章主要为大家详细介绍了如何使用Java实现文件图片的预览和下载功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... Java实现文件(图片)的预览和下载 @ApiOperation("访问文件") @GetMapping("