Clojure-JVM上的函数式编程语言(12)编译 作者: R. Mark Volkmann
?原帖地址:http://java.ociweb.com/mark/clojure/article.html#Compiling
?作者:R. Mark Volkmann
?译者:RoySong
?
编译(compiling)??? 当Clojure源文件做为脚本执行时,它们将在运行时被编译为java字节码。它们同样可以提前编译为java字节码(AOT)。
这改善了Clojure应用的启动时间,并生产了可以运用于java中的.class文件。以下是推荐的步骤:
- 为将进行编译的源文件选择一个命名空间,比如,
com.ociweb.talk
在同一个目录下面创建"src
"和"classes
"目录在源文件中需要有一个和命名空间最后一部分名字相同的源文件,比如:talk.clj,这个文件被称为主源文件
将源文件放在"src
"目录下命名空间对应的目录中,比如:主源文件应该在 src/com/ociweb/talk.clj
在主源文件的头部定义命名空间并包含:gen-class命名空间指令。比如:
(ns com.ociweb.talk (:gen-class))
在主源文件中,采用load函数根据相对路径来加载同一命名空间内的其他函数。比如:
more.clj在
src/com/ociweb下的子目录
"talk
"中,就采用(load "talk/more")
对于除了主源文件的其他源文件,采用in-ns函数来设置所属的命名空间。比如:在
more.clj的头部添加
(in-ns 'com.ociweb.talk)
将"src
"和"classes
"目录添加到REPL的classpath中。如果一个脚本用来运行REPL,那么需要修改这个脚本启动一个REPL使用compile函数来编译指定命名空间中所有的源文件,格式是
(compile 'namespace)。比如:
(compile 'com.ociweb.talk)
??? 每个函数会产生一个独立的.class文件,这些.class文件会被写入到"classes
"文件夹下面对应命名空间的目录结构下面。
?
??? 如果编译过的命名空间中拥有一个叫做-main的函数,那么它就能够作为一个Java应用运行。命令行参数会作为参数传递
给这个函数。比如,如果talk.clj包含一个
叫做-main的函数,那么它就可以像下面这样运行:
???? 下面是一个java源文件
Main.java,在
src和
classes同样的目录下:
import com.ociweb.clj.Demo; // class created by compiling Clojure source filepublic class Main { public static void main(String[] args) { String message = Demo.getMessage("Mark"); System.out.println(message); }}???? 下面是构建和运行它的步骤:
首先切换当前目录到包含
src和
classes的目录下
通过键入"clj
"来启动一个REPL键入"(compile 'com.ociweb.clj.Demo)
"退出REPL(ctrl-d或者ctrl-c)键入"javap -classpath classes com.ociweb.clj.Demo
"来查看已生成类中的方法键入"javac -cp classes Main.java
"键入"java -cp .:classes:path/clojure.jar Main.java
",在win平台下用分号替代冒号获得的输出应该是"Hello, Mark!
"????实际上还有更多的高级编译特性,你可以去 http://clojure.org/api/查看
gen-class宏的API文档,同样也可以
去http://clojure.org/compilation/看看。