Edited at
ClojureDay 9

ClojureCLRあれこれ

More than 5 years have passed since last update.


ClojureCLR

ClojureCLRは、windowsの.net環境向けに作られたClojure実行環境です。

現在は、Clojureのgithubアカウントに統合されて、開発が進んでいます。

https://github.com/clojure/clojure-clr/wiki

githubのコミット履歴を確認すると、jvm向けのコミットに対応したポートを作成しつつ、CLR独自の対応を進めていることが分かります。

最新版は、Clojure 1.5.1に対応してます。

また、徐々にですがMono環境への対応も進めています。

以下、Mono環境での話を進めていきます。


基本コマンド

REPLの実行は、mono Clojure.Main.exe です。 java -cp clojure-1.5.1.jar clojure.main にあたります。

コンパイルの実行は、mono Clojure.Compile.exe です。

hoge.clj ファイルから hoge.clj.dllファイルが作成されます。

nsにgen-classの指定がある場合は、exeファイル(.net環境の実行ファイル)が作成されます。


ライブラリ

ライブラリが、clojureの関数のみに依存している場合は、そのまま利用できますが、

JVMに依存しているライブラリは置き換えが必要です。


coreライブラリ

coreライブラリ中のclojure.javaネームスペースについては、clojure.clrに置き換えてあります。


  • clojure.clr.io (clojure.java.io)

  • clojure.clr.shell (clojure.java.shell)


contributeライブラリ

clojure のgithubには、下記の8つが登録されています。


  • clr.data.json

  • clr.data.generators

  • clr.test.generative

  • clr.tools.nrepl

  • clr.tools.namespace

  • clr.tools.analyzer

  • clr.tools.logging

  • clr.tools.trace

contributeライブラリでは管理者が別になるため、同じネームスペースでは管理せずに、

java APIに依存したライブラリを移植して、clrを先頭に付けたライブラリを用意しています。


その他


  • cljclr.tools.cli (clojure.tools.cli)

contributeに登録されていないライブラリです。

ネームスペースは、現在のところclrではなくcljclrを使っているようです。


nuget

nugetには、7つのパッケージが登録されています。

http://www.nuget.org/packages?q=clojureclr


  • Clojure By: dmiller kocubinski aaronc

  • ClojureClrEx By: kocubinski aaronc


  • clojure.data.json By: dmiller


  • clojure.tools.namespace By: dmiller


  • clojure.data.generators By: dmiller


  • clojure.test.generative By: dmiller


  • cljclr.tools.cli By: rippinrobr


ClojureCLRをビルドするときにtest関連プロジェクトで必要なため、nugetで管理しています。


lein-clr

Clojure.Main.exeは、Windowsのコマンドプロンプトを前提に設計されており、うまく使えない状況のため、MonoからREPLを操作するには、nrepl経由の操作が必要になります。

javaでleinプロジェクトを作成することになりますが、

手軽に試せるので、こちらを紹介して記事を終わりにしたいと思います。


事前準備

monoとleiningenは、別途用意してください。

OSXの場合、

monoは、XamarinStudioと一緒または、公式ページからMonoのRuntimeを入れることができます。

leiningenは、homebrewから$ brew install leiningenで、インストールできます。


プロジェクト作成

プロジェクトを作成します。

$ lein new lein-clr hello

$ cd hello


ClojureCLRのダウンロード

ダウンロードします。

$ wget http://jaist.dl.sourceforge.net/project/clojureclr/clojure-clr-1.5.0-Release-4.0.zip

$ unzip clojure-clr-1.5.0-Release-4.0.zip


設定

project.clj内で、CLJCLR14_40環境変数にClojureCLRが存在する前提になっているので、今回はそのまま設定します。

$ export CLJCLR14_40 = `pwd`/Release


REPL実行

nrepl経由で、REPLを実行します。

$ lein clr repl

user=> *clojure-version*

{:major 1, :minor 5, :incremental 0, :qualifier ""}

となります。


メイン関数実行

main関数を実行します。

$ lein clr run -m hello.core x y z

true

Received args: x y z

で、src/hello/core.cljのコマンドライン引数を表示する-main関数が実行されました。


コンパイル

バイトコードにコンパイルします。

$ lein clr compile :all

Compiling hello.core to /Users/kyusa/Works/test/hello/target/clr/bin -- 122 milliseconds.

Compiling hello.core-test to /Users/kyusa/Works/test/hello/target/clr/bin -- 80 milliseconds.


exeファイル作成

src/hello/core.clj(:gen-class)を追加してコンパイルします。


src/hello/core.clj

(ns hello.core

(:gen-class))

$ lein clr compile :all

Compiling hello.core to /Users/kyusa/Works/test/hello/target/clr/bin -- 149 milliseconds.

Compiling hello.core-test to /Users/kyusa/Works/test/hello/target/clr/bin -- 77 milliseconds.

$ ls target/clr/bin

hello.core.clj.dll hello.core.exe hello.core_test.clj.dll

今度は、exeファイルが作成されました。


exeの実行

それでは、exeファイルを実行します。

$ MONO_PATH=$CLJCLR14_40 mono target/clr/bin/hello.core.exe x y z

Received args: x y z

monoで参照するdllファイル(アセンブリファイル)のパス(javaの-cpにあたります)は、MONO_PATH環境変数で指定できます。

参考サイト(MONO_PATH)

http://kakurasan.ehoh.net/summary/lib.exec.mono.html

http://www.mono-project.com/Best_Practices


AOT

事前コンパイルして、起動時間を短縮できます。

mono --aot Release/*.dll

mono --aot target/clr/bin/*.dll

今回、エラーが出てしまい、うまくAOTコンパイル出来ませんでした。

下記は、別途用意したClojureCLRで確認した結果です。

AOT前

$ MONO_PATH=$CLJCLR14_40 time mono target/clr/bin/hello.core.exe x y z

Received args: x y z

1.56 real 1.52 user 0.04 sys

AOT後

$ MONO_PATH=$CLJCLR14_40 time mono target/clr/bin/hello.core.exe x y z

Received args: x y z

0.68 real 0.66 user 0.02 sys

JITおよびAOTの利点と欠点は、下記のサイトなどを参考にしてください。

http://www.ibm.com/developerworks/jp/java/library/j-rtj2/


LLVMバックエンド

また、monoではVMにllvmが利用できますので試してみましょう。

OSXの場合、libmono-llvm.bundle(soのかたまり)ファイルを参照するため、LD_LIBRARY_PATH環境変数の指定が必要です。

LD_LIBRARY_PATH=/Library/Frameworks/Mono.framework/Versions/Current/lib MONO_PATH=$CLJCLR14_40 time mono --llvm target/clr/bin/hello.core.exe x y z

Received args: x y z

5.69 real 5.63 user 0.04 sys

初期化の実行に時間がかかるため、単純な場合はあまり意味がありませんが、

科学計算などでは効果があるようです。

以上で終わりです。