JVMのような業界標準のプラットフォームに対して、顧客やステークホルダーは相当な額の投資を行い、そのパフォーマンスやセキュリティ、安定性に快適さを感じている。Java開発者たちは動的言語の簡潔さや柔軟性、生産性をうらやんでいるかもしれないが、顧客が認めるインフラでの実行、既存のコードベースやライブラリへのアクセス、パフォーマンスを気にしている。さらに、ネイティブスレッドとロックによる並行処理の問題にまさに直面している。Clojureはこうした文脈での実用的で動的な言語設計の努力の成果だ。ClojureはJavaが適している領域にふさわしい汎用言語になろうとしている。Clojureは、並行プログラミングの未来には現在普及している度を越した変更(mutation)はなくなるべきだ、という現実を反映している。
Clojureはその目標を次の方法で達成している: 業界標準でオープンなプラットフォームJVMを受け入れること、偉大なるLispを現代化すること、イミュータブルで永続的なデータ構造で関数型プログラミングを促進すること、ソフトウェアトランザクショナルメモリと非同期のAgentによって並行処理を組み込みでサポートすること。その結果は、堅牢で実用的で高速な言語だ。
Clojureは 状態とアイデンティティ に対して独自のアプローチをとっている。
なぜ私はさらに別のプログラミング言語を書いたのか? それは基本的に私が次のものを求めていたからだ:
Lisp
関数型プログラミングのための言語
確立されたプラットフォームと共存できる言語
並行処理のために設計された言語
そして、そういうものは見つけられなかったからだ。以下がClojureの背景にある動機となったアイディアのいくつかだ。
たびたび模倣され略奪されてきたが、いまだ複製されるには至っていない
ラムダ計算は極めて小さなコアをもたらす
ほとんどシンタックスがない
いまだ核心的な強みであるデータとしてのコード(code-as-data)とシンタックスの抽象化
標準のLisp (Common LispとScheme)はどうだろうか?
標準化以降のイノベーションが遅い/ない
コアとなるデータ構造がミュータブルで、拡張もできない
並行処理が仕様に含まれていない
JVM向けの良い実装がすでに存在する(ABCL, Kawa, SISCなど)
標準のLispはそれぞれ固有のプラットフォームになっている
Clojureは後方互換性による制約のないLispだ
データとしてのコード(code-as-data)というパラダイムをマップとベクターにまで拡張している
デフォルトでイミュータブルになっている
コアのデータ構造は拡張可能な抽象だ
プラットフォーム(JVM)を受け入れている
イミュータブルなデータ + 第一級関数
Lispでは規律や規約によって常に可能だった
しかしデータ構造が変更され うる ものであれば変更されないと推定するのは危険だ
伝統的なLispでは、リストというデータ構造だけが構造的に再帰的だ
純粋関数型言語は強い静的型付けである傾向にある
みんなに適しているわけではないし、あらゆるタスクに適しているわけでもない
Clojureは動的であることを重視する関数型言語だ
すべてのデータ構造はイミュータブルで永続的で再帰をサポートしている
異なる型の値が混在したコレクションや戻り型
動的ポリモーフィズム
OSではなくVMが未来のプラットフォームであり、次のものを提供する:
型システム
動的な強制と安全性
ライブラリ
OSの抽象化
非常に多数の 機能の集合
組み込みとサードパーティ
メモリと他のリソースの管理
GCは言語ではなくプラットフォームの機能である
バイトコード + JITコンパイル
ハードウェアの抽象化
プラットフォームとしての言語 vs. 言語 + プラットフォーム
古いやり方 - 各言語がそれぞれランタイムを定義する
GC、バイトコード、型システム、ライブラリなど
新しいやり方(JVM, .NET)
言語とは独立した共通のランタイム
プラットフォームのために構築された言語 vs プラットフォームにポートされた言語
多くの新しい言語はいまだ「プラットフォームとしての言語」というアプローチをとっている
ポートされる際にプラットフォーム上のプラットフォームという問題を抱えることになる
メモリ管理、型システム、スレッドの問題
ライブラリの重複
元の言語がC言語をベースにしていても、C言語で書かれた一部の拡張ライブラリはついてこない
プラットフォームは顧客に指定されている
「JVM(または.NET)上で実行しなければならない」vs「UNIX(またはWindows)で実行しなければならない」
JVMは実績と信頼できるレベルを確立してきた
今やオープンソースでもある
他のコードとの相互運用が求められる
C言語との連携では最近では不十分になってきている
Java/JVMは言語 + プラットフォーム
もともとそうだったわけではないが、JVM向けの他の言語は常に存在し、今やSunにも受け入れられている
Javaは冗長で表現力が不十分になりがちだ
第一級関数を欠き、型推論がない、など
Javaを呼び出し取り込む能力は決定的に重要だ
Clojureは言語であり、JVMがプラットフォームだ
シミュレーションから生まれ、今ではあらゆるものに、時には適していないものにさえ利用されている
Java/C#によってあらゆる状況で奨励されてきたが、それはJava/C#がそれ以外の(慣用的な)方法を欠いていたためだ
ミュータブルでステートフルなオブジェクトは新たなスパゲッティコードだ
理解するのもテストするのも推論するのも難しい
並行処理にとって災難だ
継承はポリモーフィズムを実現する唯一の方法ではない
「10個のデータ構造それぞれに操作する関数が10個ずつあるより、1個のデータ構造を操作する関数が100個あるほうが良い。」 - Alan
Perlis
Clojureはデータ構造をインターフェースで表現されたイミュータブルなオブジェクトとしてモデル化し、それ以外の方法で独自のクラスシステムを提供していない
少数の基本的なデータ構造(seq, map, vector, set)に対して定義された多数の関数
JavaでJavaを書き、ClojureからJavaを取り込み拡張する
switch文や構造的なマッチなどは脆いシステムをもたらす
ポリモーフィズムは拡張可能で柔軟なシステムをもたらす
Clojureのマルチメソッドはオブジェクト指向と型からポリモーフィズムを分離したものだ
複数の基準での分類をサポートしている
静的、動的または外部的なプロパティ、メタデータなどによってディスパッチする
イミュータブルであることによって多くの問題はなくなる
スレッド間で自由に共有できる
しかし、状態の変更はシミュレーションや外部世界に対するプログラムでのプロキシとして現実に必要なものだ
ロックは繰り返し正しく行うにはあまりにも難しい
ClojureのソフトウェアトランザクショナルメモリとAgentのシステムはその困難な部分を担っている
要するに、ClojureはJVM向けで強力な並行処理サポートを備えた関数型のLispとして独自のニッチを占めていると私は考えている。 特徴 や Clojureを始める を確認しよう。