Leiningen を使って Clojure を書いてみる
Lisp 方言の一つ、Clojure。JVM や .NET で動作するのが特徴で、Java コードを混ぜて書けたりするらしい。
そんな Clojure のビルドツールである Leiningen というモノを使って Hello World をやってみる。
- Clojure - Install Clojure
- 素の Clojure は Java と
$ brew install clojure/tools/clojure
で本体をインストールしても動くらしい
- 素の Clojure は Java と
- Packaging - leiningen - Codeberg.org
- Leiningen は Homebrew、Chocolatey の他様々な方法で配信されている
今回は MacOS なので Homebrew でインストールしてみる。
# Java も既にインストールされていたけど、多分 Oracle のサイトから JDK 8 を DL・インストールしたんだと思う
$ type java
java is hashed (/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/java)
$ java -version
Picked up _JAVA_OPTIONS: -Dfile.encoding=UTF-8
java version "1.8.0_202"
Java(TM) SE Runtime Environment (build 1.8.0_202-b08)
Java HotSpot(TM) 64-Bit Server VM (build 25.202-b08, mixed mode)
$ brew install leiningen
$ lein version
Picked up _JAVA_OPTIONS: -Dfile.encoding=UTF-8
Leiningen 2.9.10 on Java 1.8.0_202 Java HotSpot(TM) 64-Bit Server VM
まずは REPL をやってみる。
$ lein repl
Picked up _JAVA_OPTIONS: -Dfile.encoding=UTF-8
nREPL server started on port 53031 on host 127.0.0.1 - nrepl://127.0.0.1:53031
REPL-y 0.5.1, nREPL 0.9.0
Clojure 1.11.1
Java HotSpot(TM) 64-Bit Server VM 1.8.0_202-b08
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)
Results: Stored in vars *1, *2, *3, an exception in *e
user=> (println "Hello World")
Hello World
nil
user=> (exit)
Bye for now!
ふむ。
続いてプロジェクト雛形を作る。
# `app` アプリ用の雛形を使ってプロジェクトを作る
$ lein new app practice-clojure
Generating a project called practice-clojure based on the 'app' template.
$ tree -a ./practice-clojure/
./practice-clojure/
├── .gitignore
├── .hgignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── doc
│ └── intro.md
├── project.clj
├── resources
├── src
│ └── practice_clojure
│ └── core.clj
└── test
└── practice_clojure
└── core_test.clj
6 directories, 9 files
- プロジェクトを実行する
./project.clj
の :main
宣言に基づいてエントリポイントを確認している模様。
./src/practice_clojure/core.clj
の (defn -main
が実行されている。
$ lein run
Hello, World!
- 構文チェック
$ lein check
Compiling namespace practice-clojure.core
# シンタックスエラーがある場合はこんな感じ
# (コード中にデタラメな `XXXXX` と書いてみた)
$ lein check
Compiling namespace practice-clojure.core
Syntax error compiling at (practice_clojure/core.clj:4:1).
Unable to resolve symbol: XXXXX in this context
Full report at:
/var/folders/nd/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/T/clojure-000000000000000000.edn
Failed.
- テストコードの実行
$ lein test
lein test practice-clojure.core-test
lein test :only practice-clojure.core-test/a-test
FAIL in (a-test) (core_test.clj:7)
FIXME, I fail.
expected: (= 0 1)
actual: (not (= 0 1))
Ran 1 tests containing 1 assertions.
1 failures, 0 errors.
Subprocess failed (exit code: 1)
- ビルド
# `./target/` ディレクトリを消してくれる
$ lein clean
# ビルドする
$ lein uberjar
Compiling practice-clojure.core
Created /Users/Neo/practice-clojure/practice-clojure/target/default+uberjar/practice-clojure-0.1.0-SNAPSHOT.jar
Created /Users/Neo/practice-clojure/practice-clojure/target/default+uberjar/practice-clojure-0.1.0-SNAPSHOT-standalone.jar
# スタンドアロンの方は `java` コマンドで実行できる (4.8MB 程度)
$ java -jar ./target/default+uberjar/practice-clojure-0.1.0-SNAPSHOT-standalone.jar
Hello, World!
# 通常の JAR ファイルの方は別途クラスパスの組み立てが必要らしくそのままでは実行できない (14KB 程度)
$ java -jar ./target/default+uberjar/practice-clojure-0.1.0-SNAPSHOT.jar
Exception in thread "main" java.lang.NoClassDefFoundError: clojure/lang/Var
at practice_clojure.core.<clinit>(Unknown Source)
Caused by: java.lang.ClassNotFoundException: clojure.lang.Var
at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 1 more
ふーむ。Java が悪魔合体している感じでなかなか面白いな。