Clojureによるプログラミングに関する世界観です。
Clojureは、変数あるいはもっと言えば状態のとる値が不変(イミュータブル)です。不変とは、変えられないということです。
Clojureでは、「アイデンティティ」という発想をします。これは、「世界は停止しているのではない」ということ、「値は変化することがない」ということの二つの前提から、「世界はそれ自体が変化しながら、ひとつひとつは変化しない値を、常に連続的に生み出している」ということです。
これは、歴史のようなものだと考えれば分かりやすいかもしれません。世界は停止しているわけではなく、アイデンティティの「持っている状態」が刻々と変化しています。その中で、それぞれの時代はたとえば「鎌倉幕府の開かれた1192年」のような値を持っています。1192年が別の時代に「変更されることは決してない」のです。
命令型プログラミングでは、メモリ上の変数を「変更」して問題を解決しますが、これは停止した世界が当たり前でのプログラミングを行っています。また、オブジェクト指向プログラミングでは、プログラムをデータを「変更」するものだとしており、それ以外のどんなこともできません。
このような停止した世界が当たり前での「変更」に基づくプログラミングでは、特に並列処理を行う場合、エラーの本質的な原因となります。
Clojureは、アイデンティティの現在の状態の値にアクセスしたり、新しい値を設定するために、「変更しない」というアプローチをとります。アイデンティティの値を変更するために、Clojureは現在のアイデンティティの状態に関連付けられている値を読み取り、純粋な関数によって古い値から新しい値を作り出し、その値をアイデンティティの新しい状態として設定するのです。
Clojureの特徴は、Lisp系の関数型言語であること。
Common LispやSchemeのようなLisp系言語は、今まで素晴らしい標準的なLisp言語でしたが、標準化以降あまり変化がありません。
しかしながら、Lisp系言語には多くの利点があります。そのひとつが、「データとしてのコード」です。
Clojureでは、Lispと同様にS式を採用しながら、リスト以外にベクター、セット、マップを表せます。リストは'(1 2 3 4 5)、ベクターは[1 2 3 4 5]、セットは#{1 2 3 4 5}、マップは{:h 1, :o 2, :g 3, :e 4}と記述されます。
Clojureは、新しいLisp系言語として、Lispと関数型言語を現代的にします。
また、ClojureはJava VM上で動くJVM系言語です。Javaの機能(たとえばSwing)をClojureから使うことができます。
Javaのクラスライブラリは、巨大な機能をもたらしてくれるだけではなく、言語そのものからプラットフォーム性を分離できます。
たとえば、RubyやPythonのようなプラットフォームと言語が結合されている言語では、WindowsとUNIXに対応させるだけでも大変な労力となります。
同時に、ClojureはJVMを用いることで、既存のシステムが「顧客によって必要とされる場合」にも、顧客への要求に対応できます。「インフラがJavaであるかWindowsであるかUNIXであるかを決めるのはあくまで顧客」です。このような既存のベースに対して、Javaプラットフォームを採用することで、Clojureはビジネス的な開発の要請にも対応できます。
以上の文章は以下の参考文献を元に記述しました。
Lispについての否定的意見として、「Lispは古い」とか、「Pythonなどのメジャーな言語に比べてライブラリやモジュールが少ない」という意見があります。
しかしながら、この意見はClojureが解決します。
Clojureは新しいですし、Java VM上で動くため、Javaの豊富なライブラリモジュールを使うことができます。
もし、マイナーかつ古いという理由でLispではなくPythonなどを使うのであれば、Clojureを検討してみてはいかがでしょうか。
ただし、僕はClojureについて批判的な意見もあります。それはカッコの種類を増やすことです。
カッコの種類を[]とか{}とかにしなくても、引数keyから値を返すget-hash-value的な関数を作るのではいけないのでしょうか。
わざわざ()以外のカッコを増やす意味があるようには思えません。リテラルとしては便利かもしれませんが、()以外のカッコが増えることでコードが醜くなるでしょう。
ただし、Lispにおいてこのようにカッコの種類を増やす動きは、Clojure以外にもあります。たとえばEgisonというLispの方言では、パターンマッチングを重視しながら、さまざまなデータ構造に対応するために[]など、()以外のカッコの種類を増やしています。新しい言語を参照してください。
ただし、新しい試みをすること自体はいいことだと思います。なんらかの素晴らしい結果に至るのであれば、それで構いません。
注記:実際には、僕はClojureのことを何も知らずにこの文章を書いています。今ドキュメントを見た範囲では、むしろletによる変数の定義や束縛、defn(名前付き関数)やfn(無名関数)による関数の引数など、さまざまな状況や場合に応じて、()ではなく[]を使ったり、というやり方をするようです。単なるハッシュテーブルを表したいわけではなく、Lispという言語に記述的な「さまざまなカッコを区別する文法」をもたらすという上で、優れた方法なのかもしれません。また、get的な関数は普通にあるようです(ベクタについてはget関数でインデックスから取得できる模様)。
注記:すみません、今ANSI Common Lisp (スタンダードテキスト)を読んでいたところ、むしろCommon Lispでも配列やベクタを表すために#を使ったり、:をつけてキーワードを表現したり(さまざまなデータ構造で使う)など、Clojureと同じように特別なデータ構造を表すために標準的ではない記述をするようです。Clojureはこうした記述をよりスマートに記述できるという利点があるのかもしれません。
Lispも参照のこと。
Java(各種言語)を参照のこと。
関数型プログラミングを参照のこと。
並列処理を参照のこと。