Clojure Language Update 2019

今年もアドベントカレンダーの季節がやってきました。この1年のClojure/ClojureScript界隈の動きを振り返ってみましょう。

## Clojure 1.10.1 リリース
Clojure本体のアップデートとしては6月初旬に1.10.1のリリースがありました。マイナーバージョンのアップデートがあったのは1.5.1以来、6年のぶりのことです。Clojureは例年1年に1回のリリースをしていますが、今年は1.10.1のリリースがあったため、メジャーバージョンのアップデートはありませんでした。

1.10.1の主な変更は次の2点です：

- user.cljのロードが遅くなる問題への対処
- clojure.mainのエラーレポートの改善

それぞれの概略については以下のとおりです。

### user.cljのロードが遅くなる問題への対処

Clojure 1.10.0がリリースされた直後に[報告された問題](https://clojure.atlassian.net/browse/CLJ-2484)で、user.clj[^user.clj]のロードがかなり遅くなるという現象が確認されていました。
これは本質的にはJVM側の問題で、[クラスのstatic initializer内での特定の処理が重くなるリグレッション](https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8219233)があったようです。Clojureでは、user.cljのロードがとあるクラスのstatic initializerの中で行われていたために、user.cljの中でいろいろな処理をやっていると起動時間が長くなる問題につながっていました。

これに対処するため、user.cljのロードを含むclojure.coreの初期化処理をstatic initializerから外して、Clojureのいくつかあるエントリポイント全部で初期化処理を実行するように変更されました。ちなみに、元々のJVM自体の問題についてはすでに解決済みのようです。

[^user.clj]: user.cljはClojureの起動時に自動的に読み込まれるファイルで、REPLの初期化コード等を書いておくのに便利です。

### clojure.mainのエラーレポートの改善
Clojure 1.10.0では、REPLでのエラーメッセージが従来より簡潔に見やすくなる改善が加えられ、スタックトレースの表示も抑制されるようになりました。
しかし、この改善が反映されるのはREPLからコードを実行した場合のみで、clojure.mainにClojureファイルを渡してスクリプトとして実行した場合等ではJVMの素のスタックトレースが表示され、依然エラー原因を特定しづらい状況になっていました。これは、clojure.mainを外部コマンドとしてClojureコードを呼び出して使う開発支援系のツールで特に不便でした。

今回の改善では、そういった実行の仕方をした場合でも1.10.0で改善されたエラーレポートが反映されるように修正されました。また、スタックトレースをどこに出力するべきか(あるいは出力しないのか)をコマンドラインのオプションから指定できるような変更も加えられました。

## spec2

Clojure本体については大きな機能追加・改善がありませんでしたが、clojure.specに関しては着実な進展が見られました。clojure.specの次期プロジェクトであるspec-alpha2(通称spec2)が新たに公開され、そこで新しいspecの仕様が模索されています：

- https://github.com/clojure/spec-alpha2

将来的には今のspec(対比的にspec1とも呼ばれる)を置き換える形で統合される予定ですが、現状ではclojure.specとは独立した名前空間が割り当てられていて、spec2で定義したスペックはspec1で使えない等の点で今のところ両者に互換性はありません。

spec2としてこれまでのclojure.specに加えられた大きな変更点は以下です：

- `schema` / `select`
- 「閉じた」スペックチェック
- 実行時のスペック生成が容易に

### `schema` / `select`

`schema` と `select` は昨年のClojure/conjにてRich Hickeyが基調講演 "Maybe Not" で話していたオプショナルな値の扱いについての反省を受けての機能です。これらは基本的には `s/keys` と同様に、エンティティマップ[^entity-map]に対するスペックを定義するものです。しかし、`s/keys` のように `:req` や `:opt` で必須のキーやオプショナルに持てるキーを指定する方式ではなく、 `schema` で各キーに許される値のスペックを指定し、 `select` でその中から必須のキーを指定する、という方式を採用しています。

### 「閉じた」スペックチェック
spec1に対してよく挙がる不満として、エンティティマップに対するスペックチェックでは、マップがスペックに指定されていないキーを持っていてもエラーにならない、という点がありました。
spec2では、オプショナルに「閉じた」スペックチェックができるような変更が検討されています。「閉じた」スペックチェックを有効するためには、 `s/valid?` や `s/conform` といったAPIに以下のようにクローズするスペックを指定します。

### 実行時のスペック生成が容易に
また、これもspec1に対する不満点として、スペックをプログラム的に生成する専用のAPIがなく、必要であれば `eval` を使ってスペックフォームを実行時に評価しなければいけないという制限がありました。

spec2では新たに `resolve-spec` というAPIが追加され、スペックを定義するフォームから実行時にスペックオブジェクトを生成するのが容易になりました。

[^entity-map]: それぞれのキーに対する値ごとに指定されるスペックが異なるマップ。

## Clojure公式フォーラム始動

[Clojure Q&A](https://ask.clojure.org)というClojure公式のフォーラムも動き出しました。
誰でもClojure/ClojureScriptに関するテーマで質問ができるフォーラムですが、Clojureの開発チームのメンバーがウォッチしていて回答もしてくれるのが特徴で、必要に応じて機能追加や修正のチケットをClojureのJIRAに代理で報告もしてくれます。

また、質問や回答に対して投票もできるようになっていて、全体として従来のJIRAを使った重たい開発ワークフローよりもっとカジュアルにClojureコミュニティのメンバーがClojure開発に参加し、意見できるような場を提供することが意図されているようです。

個人的な印象としては、Clojureコミュニティの質問の場はここ数年で、StackOverflowのような従来のジェネラルな質問サイトからClojure Q&AやClojurians Slack、ClojureVerse等の専用のサービスにシェアが大きく移ってきているように感じます。

<!-- TODO
## ClojureScriptの進展
- 1.10.516
    - Predicate-induced type inference
- 1.10.597
    - Google Closure Libraryのサポート
-->

## GraalVMを使ったコマンドラインツールの台頭

昨年頃からClojureで書かれたプログラムをGraalVMの native-image を使ってネイティブコンパイルする使い方が実用化できるかどうかが模索され始めましたが、今年に入って実際にnative-imageを使った実用的なコマンドラインツールが現れ始めました。

もっとも有名なツールはClojureの新しいlintツールであるclj-kondoでしょうか。

- https://github.com/borkdude/clj-kondo

clj-kondoは新興のツールでありながら、様々な開発環境でも連携機能の対応が取られる等、コミュニティから注目されているツールの1つと言えるでしょう。広く使われているeastwoodやkibitなどのlinterに比べて起動時間が早く、flycheck等のツールと連携して使いやすい利点を持ちます。

その他のClojure製のコマンドラインツールとしては次のようなものがあります：

- [jet](https://github.com/borkdude/jet): JSON/EDN/Transitフォーマットの相互変換ツール
- [babashka](https://github.com/borkdude/babashka): Clojureを使ったスクリプティング用ツール
- [rep](https://github.com/eraserhd/rep): ワンショットのnREPLクライアント

今後ますますこういったClojure製のコマンドラインツールは広がりを見せていくものと予想されます。

## Clojurists Together

今年も1年を通してのべ11プロジェクトが[Clojurists Together](https://www.clojuriststogether.org/)の支援対象プロジェクトとして資金的な援助を受けながら開発が進められました。今年のQ3から支援プロジェクトの数が2つから4つに増えました。

- Q1
  - [Neanderthal](https://neanderthal.uncomplicate.org/)
  - [Aleph](https://aleph.io/)
- Q2
  - [Fireplace.vim](https://github.com/tpope/vim-fireplace)
- Q3
  - [CIDER](https://github.com/clojure-emacs/cider)
  - [Shadow CLJS](https://github.com/thheller/shadow-cljs)
  - [Meander](https://github.com/noprompt/meander)
  - [Calva](https://github.com/BetterThanTomorrow/calva)
- Q4
  - [Expound](https://github.com/bhb/expound)
  - [Deep Diamond (Neanderthal)](https://github.com/uncomplicate/deep-diamond)
  - [Libpython-clj](https://github.com/cnuernber/libpython-clj)
  - [Oz](https://github.com/metasoarous/oz)

Clojurists Togethrの支援プロジェクトとしては、出資者を対象としたサーベイ結果を受けて開発支援系のツールが選ばれる傾向が目立ちます。また、支援プロジェクトの枠が増えた影響か、以前は多くの人にとって馴染みのあるプロジェクトからの選定が多かったのが、最近の選考では比較的新しくまだそれほど名前が売れていないようなライブラリやツールでも有望と判断されれば選ばれるようになってきている傾向が見てとれます。

## 新興カンファレンス続々

今年も世界各地でClojureのイベントが開催されましたが、これまでカンファレンスが開かれていなかった国・地域でも続々と新しいカンファレンスが開催され、特に欧米以外の地域でのイベントが目立ってきています。

- [Clojure/north](https://clojurenorth.com/) (カナダ)
- [Clojure/South](https://clojure-south.com/) (ブラジル) 
- [Heart of Clojure](https://heartofclojure.eu/) (ベルギー)
- [Cloju.ru](https://cloju.ru/en) (ロシア)

また、これまでロンドンで開催されていたClojureXは運営をしていたSkillsMatterの倒産により今年の開催がキャンセルされてしまいましたが、その後継となるイベント [re:Clojure](https://reclojure.org) が新たに開催されることが決定しています。

## 日本語ポッドキャスト配信開始

日本のClojureコミュニティ内での新しい動きとしては、(手前味噌で恐縮ですが)日本語のClojureポッドキャスト (dosync radio) というのも始まっています。

- https://anchor.fm/dosync-radio

だいたい3〜4週間に一度のペースで、Clojureの最新情報や実際にClojureを使っていて感じることについて職業Clojurians 4人[^dosync-radio-members]で話し合ったりしています。

[^dosync-radio-members]: @athos, @ayato_p, @iku000888, @lagenorhynque

## おわりに

今年はメジャーリリースがなかったため、Clojure/ClojureScript界隈は比較的穏やかに過ぎていった印象ですが、世界各地でカンファレンスが開催され、コミュニティの盛り上がりとしてはますます活発さを拡大しているように見えます。
今後の1年に注目すると、満を持してのClojure 1.11リリースはもちろんのこと、Clojureコアとは独立に開発が進められているspec2やtools.depsでも大きなアップデートが予定されていて目が離せません:innocent: