Clojure初心者向け: プロジェクト管理ツールLeiningenのざっくり説明

### 記事の趣旨

本記事ではLeiningenの初心者向けに、Leiningenがどういうものなのか？がざっくり分かるようにまとめます。詳細な説明や挙動を知りたい方は、[公式のチュートリアル](https://leiningen.org/tutorial.html)や、GitHubのコードを読むことをお勧めします。

### Leiningenとは？

Clojureコミュニティで人気があり、広く開発に採用されている、Clojure開発に特化したビルドツールです。Leiningenを使うことには、開発を効率化する以下のようなメリットがあります。

- ライブラリを使用する際の依存関係を自動的に解決してくれます。Leiningenを使用していれば、ライブラリについて開発者がやることは大抵の場合、`project.clj`という設定ファイルに、ライブラリ名とバージョンといった情報を書くだけになります。
- プロジェクトを、JVM環境で簡単に実行できるjarファイルにビルドしてくれます。特に、全ての依存関係を含んだuberjarという形式でもjarファイルが作成でき、この場合にはJVM環境上で単体で実行可能です。
- コードの静的なチェック(`lein check`)や、自動テストの実行(`lein test`)といった、開発をサポートする簡単に行ってくれるコマンドを提供します。
- (本記事で詳しくは触れませんが) Leiningenはプラグインを追加して使用することができ、拡張性や自由度も高いです。プラグインの追加によって、デフォルトのLeiningenのコマンド以外にもサブコマンドを追加することができます。プラグインの追加に関しても、`project.clj`の`:dependencies`に記載をするだけで解決されます。

### project.cljについて

Leiningenは、projectという単位で動作します。projectとは、ソースコードと`project.clj` という設定用のファイルをセットにしたものです。`project.clj` とは、Leiningenがプロジェクトに関する設定を読み込むためのファイルで、Leiningenを使用する際には非常に重要なファイルです。

例えば、以下は`lein new app my-sample-app`のコマンド(my-sample-appというプロジェクトを、appというテンプレートに従って新規作成するというコマンドです)で生成された、テンプレートの`project.clj` の全体です。

```clojure
(defproject my-sample-app "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"
            :url "https://www.eclipse.org/legal/epl-2.0/"}
  :dependencies [[org.clojure/clojure "1.10.0"]]
  :main ^:skip-aot my-sample-app.core
  :target-path "target/%s"
  :profiles {:uberjar {:aot :all}})
```

ここでは様々な設定を行うことができますが、ひとまず抑えておくべきことは以下かと思います。

- map形式のように、キーワードと値の組で記載します。
- プロジェクト内で使用するライブラリについて、ライブラリ名とバージョンの情報を`:dependencies`の値に書いておくことで、そのライブラリの依存関係をLeiningenが解決してくれます。多くのClojureライブラリでは、そのドキュメントにLeiningen用の依存関係の記述方法が記載されているので、それを参考にするとよいでしょう。
    - 上記のサンプルでも書かれているように、Leiningenにおいては、Clojure自体も依存関係の一部として書かれます。
- `:main`の値として書かれているネームスペース中の、`-main`関数がエントリーポイントとして設定されます。上記の例では、`my-sample-app.core`の`-main`関数がエントリーポイントになります。
    - なお、上記の例では`^:skip-aot`のメタデータによりAOT (Ahead-Of-Time) コンパイルのスキップが指定されます。

### 主要なLeiningenコマンドの紹介
#### `lein repl`
REPL環境が動作し、対話的にClojureコードが実行できます。Leiningenのインストールが出来たら、一度実行してきちんと動作することを確認してみると良いでしょう。また、`require`関数を評価することで、`project.clj`に書いたライブラリを使うこともできます。

#### `lein new`
プロジェクトをテンプレートに沿って新規作成できます。開発用のプロジェクトを素早くセットアップできるので便利です。

例えば、`lein new app my-sample-app`でプロジェクトを生成して、`tree`コマンドでディレクトリ構造を確認すると以下のようになります。

```clojure
.
├── CHANGELOG.md
├── LICENSE
├── README.md
├── doc
│   └── intro.md
├── project.clj
├── resources
├── src
│   └── my_sample_app
│       └── core.clj
└── test
    └── my_sample_app
        └── core_test.clj

6 directories, 7 files
```

このように作成されたプロジェクトでは、`project.clj`にプロジェクトの設定を、`src`ディレクトリにソースコードを、`test`ディレクトリにテストコードを書いて開発をするのが一般的です。

#### `lein run`
プロジェクトのソースコードをコンパイルし、設定されたエントリーポイントからプログラムを実行します。開発中のアプリケーションの動作をテストする際や、ビルドを行わずにすぐ動作を行いたい場合に便利です。

#### `lein check`
コードの静的解析が行われます。開発中のコードに構文エラー等の問題が無いことを確認することができ、品質の向上にも役立ちます。

#### `lein test`
プロジェクト内のテストコードが実行されます。

#### `lein uberjar`
プロジェクトのjarファイルを作成するコマンドで、デフォルトでは`target`ディレクトリに2個のjarファイルが作成されます。(`project.clj`における、`:target-path "target/%s"` の部分の設定のためです。)作成したjarファイルは`java -jar [jarファイルのパス]`のコマンドで実行できます。

例えば、上記のmy-sample-appプロジェクトで、`lein uberjar`を実行すると、`my-sample-app-0.1.0-SNAPSHOT.jar` , `my-sample-app-0.1.0-SNAPSHOT-standalone.jar` という2個のファイルが作成されます。前者と後者の違いは依存関係を含むかどうかであり、後者は、依存関係を含むのでスタンドアローンで実行することが可能です。

#### `lein help` 
Leiningenにおいて利用可能なコマンドの一覧と簡単な説明が表示されます。`lein help [TASK]`の形式、例えば`lein help run`のように特定のコマンド名を指定すると、そのコマンドのより詳細な使用方法やオプションに関する情報を確認することができます。