Clojure開発環境

前置き

Clojure開発環境をセットアップしたときのメモです。3種類を試しました。

  • 梅 …JDKとClojure(jar)の最小構成
  • 竹 …Leiningenというプロジェクト管理ツールを使った構成
  • 松 …IDE(Eclipse)を使った構成

自分は、今後、Eclipseを使うつもりです。

JDK

  • Oracleのサイトからjdk-7u21-windows-x64.exeをダウンロード
  • C:\misc\oracle\jdk1.7.0_21へインストール
  • ついでにOracleの日本語サイトからJDK6のAPIリファレンスをダウンロード
  • C:\misc\oracle\jdk1.7.0_21\binへpathを通す
  • 環境変数JAVA_HOMEへC:\misc\oracle\jdk1.7.0_21をセット

Clojure 1.5.1

  • 公式サイトからclojure-1.5.1.zipをダウンロード
  • c:\wintls32\clojure-1.5.1へ解凍

REPL

REPLの起動
d:\etude\clj>java -cp c:\wintls32\clojure-1.5.1\clojure-1.5.1.jar clojure.main
Clojure 1.5.1
user=> (+ 1 2 3)
6
user=> (javax.swing.JOptionPane/showMessageDialog nil "Hello, World!")
nil

ハロー

  • Ctrl+Z, Enterで終了

コンパイル

helloプロジェクト
d:\etude\clj\hello\
  src\
    jp\
      dip\
        gpsoft\
          hello.clj
          hello\
            foo.clj
            bar.clj
  classes\
hello.clj
(ns jp.dip.gpsoft.hello (:gen-class))

(load "hello/foo" "hello/bar")

(defn -main [& args] (foo))       ;;これが public static void main(String[] args) になる。
foo.clj
(in-ns 'jp.dip.gpsoft.hello)

(load "hello/bar")

(defn foo [] (print-greeting))
bar.clj
(in-ns 'jp.dip.gpsoft.hello)

(defn print-greeting [] (println "Hello, World"))
REPLでコンパイル
D:\etude\clj\hello>java -cp c:\wintls32\clojure-1.5.1\clojure-1.5.1.jar;.\src;.\classes clojure.main
Clojure 1.5.1
user=> (compile 'jp.dip.gpsoft.hello)
jp.dip.gpsoft.hello
user=>

これで、classesフォルダ配下にクラスファイルが生成されました。

実行する
D:\etude\clj\hello>java -cp c:\wintls32\clojure-1.5.1\clojure-1.5.1.jar;.\classes jp.dip.gpsoft.hello
Hello, World

Leiningen

公式サイトのチュートリアルによれば、Leiningenは、"Maven meets Ant without the pain"のようなツールだそうです。

  • 公式サイトからlein.batをダウンロード
  • c:\wintls32へ置く
  • c:\wintls32へpathを通す
  • 環境変数LEIN_HOMEへC:\wintls32\leinをセット

このlein.batがメインプログラム、というかLein本体(jar)のラッパです。Lein本体をインストールするのにも、このlein.batを使います。

Lein本体(jar)のインストール
d:\etude\clj>echo %LEIN_HOME%
C:\wintls32\lein

d:\etude\clj>lein self-install
Downloading Leiningen now...
        1 個のファイルを移動しました。

これで、LEIN_HOMEのフォルダへLeiningenのjarが置かれました。

ここで注意点が1つ: 環境変数LEIN_HOMEの設定は必須ではなさそうです。設定した場合、そこがLeiningenのコンフィグファイル(profiles.clj)の置き場になります。もしLeiningenをカスタマイズする場合は、そこにprofiles.cljを置きましょう。ちなみに、LEIN_HOMEを設定しない場合の、デフォルトの置き場は、%USERPROFILE%\.leinです。

プロジェクト作成

プロジェクトhelloの作成
d:\etude\clj>lein new app hello
Retrieving org/clojure/tools.nrepl/0.2.3/tools.nrepl-0.2.3.pom from central
Retrieving org/clojure/pom.contrib/0.1.2/pom.contrib-0.1.2.pom from central
Retrieving org/sonatype/oss/oss-parent/7/oss-parent-7.pom from central
Retrieving org/clojure/clojure/1.2.0/clojure-1.2.0.pom from central
Retrieving clojure-complete/clojure-complete/0.2.3/clojure-complete-0.2.3.pom from clojars
Retrieving org/clojure/clojure/1.3.0/clojure-1.3.0.pom from central
Retrieving org/sonatype/oss/oss-parent/5/oss-parent-5.pom from central
Retrieving org/clojure/tools.nrepl/0.2.3/tools.nrepl-0.2.3.jar from central
Retrieving org/clojure/clojure/1.2.0/clojure-1.2.0.jar from central
Retrieving clojure-complete/clojure-complete/0.2.3/clojure-complete-0.2.3.jar from clojars
Generating a project called hello based on the 'app' template.

d:\etude\clj>cd hello

d:\etude\clj\hello>type src\hello\core.clj
(ns hello.core
  (:gen-class))

(defn -main
  "I don't do a whole lot ... yet."
  [& args]
  ;; work around dangerous default behaviour in Clojure
  (alter-var-root #'*read-eval* (constantly false))
  (println "Hello, World!"))

実行

REPLから実行
d:\etude\clj\hello>lein repl
Retrieving org/clojure/clojure/1.5.1/clojure-1.5.1.pom from central
Retrieving org/clojure/clojure/1.5.1/clojure-1.5.1.jar from central
nREPL server started on port 50571
REPL-y 0.2.0
Clojure 1.5.1
    Docs: (doc function-name-here)
          (find-doc "part-of-name-here")
  Source: (source function-name-here)
 Javadoc: (javadoc java-object-or-class-here)
    Exit: Control+D or (exit) or (quit)

hello.core=> (+ 1 2 3)
6
hello.core=> (require 'hello.core)
nil
hello.core=> (hello.core/-main)
Hello, World!
nil
  • 必要なjar(Clojure自身も含む)は、Leiningenが勝手にダウンロードする
  • ダウンロード先は、%USERPROFILE%\.m2
  • このフォルダはMavenと共有するみたい
REPLなしで実行
d:\etude\clj\hello>lein run -m hello.core
Hello, World!
  • -mで、-main関数の場所を指定
  • project.cljに、-main関数の場所を宣言しておけば、-mは不要
project.clj
d:\etude\clj\hello>type project.clj
(defproject hello "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.5.1"]]
  :main hello.core)

d:\etude\clj\hello>lein run
Hello, World!

Uberjar

uberjarは、super jarみたいな意味みたいです(uberはドイツ語のover)。Leiningenのuberjarコマンドを使うと、プログラムの実行に必要なjarを全部パッケージングしたjarを作ることができます。javaコマンドに、長々とjar名を列挙する必要が無くなるわけですね。

uberjarコマンド
d:\etude\clj\hello>type project.clj
(defproject hello "0.1.0-SNAPSHOT"
  :description "A sample project"
  :url "http://foo.bar.buz.com/"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.3.0"]
                 [org.apache.lucene/lucene-core "3.0.2"]
                 [clj-http "0.4.1"]]
  :profiles {:dev {:dependencies [[ring/ring-devel "1.2.0"]]}}
  :test-selectors {:default (complement :integration)
                  :integration :integration
                  :all (fn [_] true)}
  :main hello.core
  :aot [hello.core])

d:\etude\clj\hello>lein uberjar
Created d:\etude\clj\hello\target\uberjar+provided\hello-0.1.0-SNAPSHOT.jar
Including hello-0.1.0-SNAPSHOT.jar
Including jackson-dataformat-smile-2.0.0.jar
Including jackson-core-2.0.0.jar
Including clj-http-0.4.1.jar
Including httpclient-4.1.3.jar
Including commons-logging-1.1.1.jar
Including cheshire-4.0.0.jar
Including httpcore-4.1.4.jar
Including commons-io-2.1.jar
Including slingshot-0.10.2.jar
Including clojure-1.3.0.jar
Including commons-codec-1.5.jar
Including lucene-core-3.0.2.jar
Including httpmime-4.1.3.jar
Created d:\etude\clj\hello\target\hello-0.1.0-SNAPSHOT-standalone.jar

d:\etude\clj\hello>java -jar target\hello-0.1.0-SNAPSHOT-standalone.jar
Hello, World!

ソースのnsマクロに、:gen-classを付けるのを忘れずに。

Eclipse

  • 日本語化Eclipseのサイトからpleiades-e4.2-java_20130303.zipをダウンロード
  • 解凍して、eclipseフォルダをc:\miscへ置く
  • 起動して、D:\etude\clj\workspaceにワークスペースを作成

Counterclockwise

Counterclockwiseは、EclipseにClojureサポートを追加するためのプラグインです。

  • ソフトウェア更新サイト(メニューの[ヘルプ]→[新規ソフトウェアのインストール])としてhttp://ccw.cgrand.net/updatesite/を追加
  • 0.12.3STABLE001をインストール

プロジェクト作成

  • メニューの[ファイル]→[新規]→[プロジェクト]→[Clojure Project]
  • プロジェクト名を"hello-clj"として[完了]

Eclipseプロジェクト

  • プロジェクトは、Leiningenともマッチするように構成される
  • project.cljのdependenciesに設定された依存Jarが、クラスパスに自動追加
  • 依存Jarは勝手にダウンロードする
hello-clj.core
(ns hello-clj.core)

(defn -main
  "I don't do a whole lot."
  []
  (println "Hello, World!"))
  • ソースファイルのコンテキストメニューから、[実行]→[Clojure Application]で、REPLが起動
  • 当該ソース内で名前空間を定義しているなら、そこへ(in-ns)した状態でREPLが起動

REPL

  • Leiningenでも実行可能
D:\etude\clj\workspace\hello-clj>lein run -m hello-clj.core
Hello, World!

実行構成

  • コンテキストメニューから、[実行]→[実行の構成]
  • [Evaluate Clojure source file(s)]に、実行時にロードしたいファイルを登録

実行構成

[Run with REPL]のツールチップには、以下のように書いてあります。

If checked, all files listed will be loaded with the -i option, and a new REPL view
will be opened and connected to the new process.
If unchecked, all files listed will be loaded with the -i option, except for the last
which will be loaded as a script.

-iオプションというのが意味不明ですが、REPLを起動したいならチェックし、REPLを使わずに直接実行したいならチェックを外せば良いでしょう。

チェックした場合、REPL起動直後は名前空間がuserになってしまうので、in-ns関数を使って所望の名前空間に変える必要があります。

チェックを外した場合、ファイルリストに登録した最後のファイルが起動スクリプトになります(ただし、順番を任意に変えることはできない!!)。defとかdefnするだけでは何も起きません。エントリポイントの関数を呼ぶとか、何かする必要があります。例えば、こんな感じです。

launch.clj
(in-ns 'hello-clj.core)

(-main)

ツールバーにも登録しておきましょう。

お気に入り

コンソールビューを出しておけば、printlnの出力が表示されます。

  • [ウィンドウ]→[ビューの表示]→[コンソール]

ノウハウ

便利なショートカットキー:

エディタ上でCtrl+Alt+L
当該ソースファイルをREPL上でロードする。
エディタ上でCtrl+Alt+N
REPLの名前空間を、当該ソースファイルが定義した名前空間へ切り替える。
エディタ上でCtrl+Alt+K
当該ソースファイルをコンパイル。

任意のシンボル上にマウスをホバーさせると、ツールチップにドキュメント(Doc-string)を表示してくれます。ただしこれは、REPL起動中のみ機能します。REPLを起動してないと、"no doc found"になってしまいます。

ソースファイルのディレクトリ構成を変えたり、名前空間の名前を変えたりすると、どうやってもコンパイルが通らなくなることがありました。たしか、classesフォルダを削除すれば解消できたような気がしますが、定かではありません。

追記

Eclipse

上記のEclipseは、バージョン4.2(Juno)64bit版を日本語化したものです。Junoを使うのは初めてではないのですが、今回作った環境では、どうもキーバインドの設定がうまく効かないことがあるようです。例えば、Ctrl+Xで切り取るようにしても、Emacsの2ストロークキーが発動してしまいます。4.3(Kepler)でも同様でした。Ctrl+Zのアンドゥーも効きません。

そこで、3.7(Indigo)に戻しました。日本語化してない素のバージョンです。

  • eclipse-java-indigo-SR2-win32-x86_64.zip

If you are a vim guy...

あなたがvimmerなら、Vim for Windows セットアップメモが参考になるかもしれません。

Last modified:2013/10/02 20:05:53
Keyword(s):
References:[くろニャァ ~ 最初の一歩] [FP: 関数型プログラミング] [Midje ~ Clojureのテストフレームワーク(Part1)]
This page is frozen.