無料のKindleアプリをダウンロードして、スマートフォン、タブレット、またはコンピューターで今すぐKindle本を読むことができます。Kindleデバイスは必要ありません。
ウェブ版Kindleなら、お使いのブラウザですぐにお読みいただけます。
携帯電話のカメラを使用する - 以下のコードをスキャンし、Kindleアプリをダウンロードしてください。
プログラミングClojure 単行本(ソフトカバー) – 2010/1/26
Clojure(クロージャ)は、関数型プログラミングや並行プログラミングといった、先進的で強力なプログラミング手法をサポートするプログラミング言語。進んだパラダイムと実用性との見事なバランス、オープンソースでの公開やJava との親和性の高さなどから、注目を集めつつある。
本書は、ユーザにとって必要な知識を十分に解説したClojure の実践的な解説書Pragmatic Bookshelf 社の“Programming Clojure”を翻訳したもの。基本部分から応用的なところまでを網羅的に解説している。
- 本の長さ304ページ
- 出版社オーム社
- 発売日2010/1/26
- ISBN-104274067890
- ISBN-13978-4274067891
商品の説明
著者からのコメント
元来、Lisp 族言語はプログラミング言語のアイディアの実験場だった。Lispの本質とも言える拡張性の高さ、およびコアとなる仕様のシンプルさがアイディアを実装し、使い、改善してゆくプロセスを容易にするからだ。しかし言語の自由さと安定した仕様との間には相反する関係がある。ひとたび言語が広く使われだすと、言語の根幹にかかわる仕様、例えば評価規則を変えるなどの変更は難しい。したがって、伝統から離れる新しいアイディアを実現した言語も、ユーザが増えるにつれ漸進的な進化に落ち着いてゆく。
そうやって枯れることは諸刃の剣だ。漸進的進化に安住してしまうと発想の源が制限されてしまう。時には連続性を捨てた異端児が生まれることが、言語の一族が進化してゆくためには必要なのだ。Clojure は、Lisp 一族にとって非連続な異端児と言える。Clojure の新しいアイディアが実戦を経て生き残るかどうかを見極めるにはまだ時間が必要だが、特に並行モデルに関しては他の言語を大いに刺激するものだろう。
もっとも、Lisp に馴染みのない読者にとってはClojure も他のLisp も似たようなものに見えるだろう。本書はLisp の知識を持たない人でも自然に読み進められるようになっているので、Lisp がどうの、という話は気にせずに(そして見慣れぬ括弧にあまり惑わされないようにして)、ひとまずは本書の例を実際に試してみてほしい。特に、小さいが強力な部品を組み合わせることで、高機能を簡潔に実現できるところに注目してみよう。そこには、言語を超えた普遍的なアイディアが示されている。本書で得た知識はClojure を使うのに役立つだけでなく、他の多くのメインストリーム言語に取り入れられつつある関数型プログラミングの概念を掴むのに効果を発揮するだろう。
......
(「訳者あとがき」より)
出版社からのコメント
Clojure(クロージャ)は、関数型プログラミングや並行プログラミングといった、先進的で強力なプログラミング手法をサポートするプログラミング言語。進んだパラダイムと実用性との見事なバランス、オープンソースでの公開やJavaとの親和性の高さなどから、注目を集めつつある。
本書は、ユーザにとって必要な知識を十分に解説したClojureの実践的な解説書Pragmatic Bookshelf社の"Programming Clojure"を翻訳したもの。基本部分から応用的なところまでを網羅的に解説している。
★このような方におすすめ
プログラマ全般
特に、Haskell、Erlang、 Lispなどに興味がある先進的なプログラマ
著者について
Stuart Halloway はRelevance, Inc. の共同創設者であり、CEO を務める。Relevance が提供するサービスは、アジャイル手法および、Ruby やClojure といった先端技術にかかわる開発、コンサルティング、トレーニングである。本書以外の著書にComponent Development for the Java Platform(Addison-Wesley, 2001)やRails for Java Developers(Pragmatic Bookshelf, 2007)などがある。
訳者 川合史朗(かわいしろう)
Scheme Arts, LLC 代表。Scheme 処理系Gauche をツールとしてソフトウェアコンサルティングを行う。強みはネットワーク、CG コンテンツ制作プロセス、言語処理系。2002 年まではSquare USA Inc. にて、Senior Software EngineerとしてCG 技術開発に従事。たまに地元ホノルルの劇場で舞台に立つ役者にもなる。訳書に『ハッカーと画家』(オーム社、2005 年)、共著に『プログラミングGauche』(オライリージャパン、2008 年)がある。
About this Title
Getting Started
まず、Clojure を魅力的なものにしている特徴的な機能をざっと見ることから始めよう。
• エレガントさ、高い表現力
• コードとデータが同じ表現であるというLisp の力
• 容易で高速なJava とのやりとり
• すべてのデータを統合するシーケンスライブラリ
• 再利用が容易で正しいコードを書きやすい関数型プログラミング
• ロック管理の悪夢から開放された並行性
この機能のリストは本書全体のロードマップにもなっているので、今ここで細かいことが分からなくても心配しないでいい。それぞれの機能が、後
で1 章まるまる割いて説明される。
次に、早速だが小さなアプリケーションを組み立ててみることにしよう。また、本書の後のほうで使うことになる、大きな例をロードして実行する
方法についても説明する。
最後に、依存関係を基にしたビルドシステムであるLancet を紹介する。Lancet は本書を通じて作り上げてゆくことになるサンプルアプリケーショ
ンだ。
1.1 なぜClojure なのか
ぱっと見ると、Clojure は近未来からやってきた汎用言語のようだ。Clojureの関数型プログラミングとソフトウェアトランザクショナルメモリは
、現在広く使われているプログラミング手法からずっと進んでおり、マルチコアハードウェアに非常に適している。
一方でClojure は過去と現在にもしっかりと足をつけている。Clojure はLispとJava 仮想マシンとを結びつけたのだ。Lisp はプログラミングの歴
史の黎明期から現在に至る叡智をもたらし、Java は頑健性、膨大なライブラリ、そして現代のあらゆる場所で使われているプラットフォームをも
たらした。
この2 つの組み合わせがどんなに強力か、これから見ていくことにしよう。
Clojure はエレガントだ
Clojure のコードはS/N 比が高く、結果としてプログラムは短くなる。短いプログラムは開発のコストを抑えられ、楽に運用を始められ、メンテナ
ンスも容易だ。*1 プログラムが単に短いというのではなく、小さくまとまっているということが特に重要である。例えばApache Commons にある次
のJava コードを見てみよう。
Icode/snippets/isBlank.java
public class StringUtils {
public static boolean isBlank(String str) {
int strLen;
if (str == null || (strLen = str.length()) == 0) {
return true;
}
for (int i = 0; i if ((Character.isWhitespace(str.charAt(i)) == false)) {
return false;
}
}
return true;
}
}
isBlank メソッドは文字列がブランクかどうか、つまり空文字列あるいは空白文字だけからなる文字列かを調べる。Clojure で同じ機能を書くと次
のコードになる。
Icode/examples/introduction.clj
(defn blank? [s] (every? #(Character/isWhitespace %) s))
Clojure のほうが短いが、より重要なのは、Clojure のほうが簡潔だということだ。変数も、書き換えられる状態も、分岐もない。これは高階関数
のおかげだ。高階関数とは、関数を引数にとったり戻り値として返すような関数のことだ。every?は関数とコレクションを引数に取り、コレクショ
ン中のすべての要素について関数が真を返したときにtrue を返す。
Clojure 版は分岐が無いので、読むのもテストするのも容易だ。こういった利点はプログラムが大きくなるにつれ威力を発揮するようになる。また
、コードは簡潔であるけれど読みやすい。実際、上のClojure プログラムはブランク文字列の定義のように読める。「文字列は、その中のすべての
文字が空白であればブランク文字列である」(a string is blank if every character in it is whitespace)、と。これはCommons のメソッドよ
りもずっといい。Commons のメソッドのほうはブランク文字列の定義がループやif 文といった実装上の詳細の中に埋もれてしまっている。
次の例として、Java で単純なPerson クラスを定義してみよう。
Icode/snippets/Person.java
public class Person {
private String firstName;
private String lastName;
public Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
一方、Clojure でのperson の定義は1 行だ。
(defstruct person :first-name :last-name)
defstruct と関連する関数については2.1「マップ、キーワード、構造体」(p. 32)で詳しく扱う。
桁違いに短いというだけでなく、Clojure のアプローチはperson が変更不可能であるという点でも異なる。変更不可能な構造は自然にスレッドセ
ーフになる。構造体のアップデートは、第6 章「並行プログラム」(p. 157)で扱う、参照、エージェント、アトムといった機能を組み合わせるこ
とで実現できる。構造体が変更不可能であることから、Clojure ではhashCode() とequals() の正しい実装が自動的に実現できる。
Clojure にはたくさんのエレガンスが備わっているが、それでも足りないものがあれば、あなたは自分でそれを追加できる。それがLisp の力だ。
Clojure は「Lisp・リローデッド」だ
Clojure はLisp である。何十年にもわたって、Lisp の熱心な支持者は、あらゆる言語に対してLisp の利点を主張してきた。けれどもLisp による
世界征服計画はなかなか進んでいないようだ。
他のLisp と同様に、Clojure も2 つの壁を乗り越えなければならない。
• Lisp プログラマに対しては、Clojure がLisp のエッセンスを継承しているということを納得させる。
• 同時に、過去のLisp が成功しなかった、より広いプログラミングコミュニティからの支持を得る。
Clojure はLisp のメタプログラミングの力を提供すると同時に、いくらかの構文的な拡張を導入して非Lisp プログラマにも親しみやすいようにす
ることで、これらの壁を越えようとしている。
どうしてLisp なんだろう?
Lisp は構文をほとんど持たない代わりに、とても小さな核となる言語と強力なマクロ機能を持つ。それらを使って、プログラマはLisp を目的とす
る設計に合わせて変化させることができる。設計のほうを言語に合わせて修正するのではなく。一方、Java ではどうだろう。次の例をみてほしい
。
public class Person {
private String firstName;
public String getFirstName() {
// 続く...
getFirstName() はメソッドだ。メソッドは多態的で、プログラマが好きなように定義を変えられる。けれども、この例に出てくる他の単語のほと
んどは、言語によって意味が決められてしまっている。ときに、これらの単語の意味を変えたいと切に思うことがあるはずだ。例えば次のような例
が考えられる。
• private を「製品コード中ではprivate だけれど、シリアライゼーションとユニットテストからはアクセス可能である」というふうに再定義する
。
• 特に指定しない限りprivate なフィールドのgetter とsetter を自動生成するようにclass を再定義する。
• あるいは、class に対してそのライフサイクルイベントへのコールバックを提供するサブクラスを作成する。ライフサイクルイベントとは、例え
ばそのクラスのインスタンスが作られるたびにイベントコールバックを呼び出すといったものだ。
こういった拡張すべてを必要とするプログラムを私はいくつも見てきた。これらの拡張無しでは、プログラマは似たようなコードを何度も何度も書
くことになり、ミスも混入しやすい。文字どおり何百万行にも及ぶコードが、プログラミング言語の欠けている機能を補うために書かれてきた。
ほとんどの言語では、上に挙げたような機能を言語に組み込んでもらうには言語実装者にお願いして待つしかない。Clojure なら、あなたは自分の
言語機能をマクロを使って追加することができる(第7 章「マクロ」(p. 193))。Clojure 自身さえ、defstruct のようなマクロを使って書かれ
ているのだ。
(defstruct person :first-name :last-name)
違うセマンティクスが必要なら、自分のマクロを書けばいい。もしフィールドが静的に型付けされて、しかもnull チェックの有無が指定できるよ
うなstructの拡張が欲しければ、そういったdefrecord マクロを書くことができる。例えばそれはこんな風に使えるだろう。
(defrecord
person [String :first-name String :last-name]
:allow-nulls false)
言語の中からその言語を変えてしまうというのはLisp に特有の利点だ。この利点は以下に挙げるようなさまざまな側面を持つ。
• Lisp は同図像性(homoiconic)*2を持つ言語だ。すなわち、Lisp のコードはLisp のデータでもある。これによって、「プログラムを生成する
プログラム」というのが簡単に書けるようになる。
• また、言語のすべてが、常にそこにある。Paul Graham はエッセイ「技術野郎の復讐」*3*4で、これがどうしてそんなに強力なのかを説明してい
る。
Lisp の構文はまた、演算子の優先順位や結合性といった規則を不要にしている。演算子の優先順位だとかどの演算子が右結合でどれが左結合かと
いった表は本書のどこにもない。すべて括弧で表現するので、曖昧性が無いからだ。
Lisp のこの単純で規則的な構文はしかし、少なくとも初心者にとっては欠点にもなりうる。Lisp のコードは括弧だらけになり、またデータ型とし
てリストばかりが強調されてしまうからだ。Clojure はLisp 以外のプログラマがLisp に近づきやすくなるようにいくつかの工夫をしている。
括弧の少ないLisp
Clojure は他のLisp から来たプログラマに対して強力な利点を提供する。
• Clojure はLisp の具体的なリスト構造をシーケンスと呼ばれる抽象構造として一般化した。シーケンスは、リストの力を保ったまま、その力を
他のさまざまなデータ構造へと適用可能にしたものだ。
• Clojure はまた、JVM を前提とすることで、強力な標準ライブラリを手に入れ、多くのプラットフォームに展開することが可能になった。
• Clojure のシンボル解決方法とクオート構文は、よくあるマクロの多くを簡単に書けるようにする。
もっとも、Clojure のプログラマの多くはLisp に触れるのが初めてで、おそらくLisp と聞くと悪名高い括弧のことを思い出すだろう。Clojure は
確かに括弧を使うし、それによるLisp の力を保ってはいるが、いくつかの点で従来のLispの構文を改善している。
• まず、Clojure はリスト以外にも正規表現、マップ、セット、ベクタ、およびメタデータといったさまざまなデータ構造に対してリテラル構文を
提供している。これによってClojure のコードは他のLisp ほどに「リストだらけ」には見えない。例えば関数の引数はリスト() ではなくベクタ[]
を使って指定される。
Icode/examples/introduction.clj
(defn hello-world [username]
(println (format "Hello, %s" username)))
ベクタを使うことで、引数リストがぱっと見て分かりやすくなり、Clojureの関数定義は読みやすくなる。
• また、他の多くのLisp と違い、Clojure ではコンマは空白文字だ。コンマを使うことでデータ構造を読みやすく書くことができる。例えばベク
タは、コンマを使うと他の言語の配列のように見える。
; ベクタを他の言語の配列のように表記する
[1, 2, 3, 4]
-> [1 2 3 4]
• 典型的なClojure コードは、必要以上に括弧をネストすることはしない。例えば、Common Lisp にもClojure にもあるcond マクロを見てみよ
う。cond はテスト式と結果式からなるいくつかのペアに展開され、最初にtrue を返すテスト式に対応する結果式が評価され返される。Common
Lisp ではテスト式と結果式の各ペアが括弧でくくられる。
; Common Lisp のcond
(cond ((((> x 10) "more"))
Clojure は余分な括弧を使わない。
; Clojure のcond
(cond ((> x 10) "more")
これは好みの問題で、どちらの方式にもそれぞれ支持者がいる。重要なのは、Clojure では、Lisp の力を失わない限りにおいて、できるだけLisp
っぽくないようにできる機会があればそちらを選択しているということだ。Clojure は、Lisp のエキスパートにとっても初心者にとっても、優れ
たLispである。
Clojure は関数型言語である
Clojure は、Haskell のように純粋ではないが、関数型言語だ。関数型言語は次に挙げる特徴を持っている。
• 関数は第一級のオブジェクトである。つまり実行時に関数を作ったり、引数に渡していったり、戻り値にしたりと、他のデータ型と同じように使
える。
• データは変更不可能である。
• 関数は純粋、つまり副作用を持たない。
多くの目的において、関数型プログラムは理解しやすく、エラーが入り込みにくく、そしてずっと再利用しやすい。例えば、次の短いプログラムは
データベースを検索して``Requiem'' と名の付く曲を作った作曲家を列挙するものだ。
(for [c compositions :when (= "Requiem" (:name c))] (:composer c))
-> ("W. A. Mozart" "Giuseppe Verdi")
for はループではなく、リスト内包表記を表現する。上のコードは次のように読める。「compositions 内のそれぞれのc について、もしc のname
が"Requiem"であれば、c のcomposer を結果とせよ。」リスト内包表記については4.2「シーケンスの変換」(p. 102)で詳しく解説する。この例
は、望ましい特徴を4 つ示している。
• まずこのコードは簡単だ。ループも、変数も、変更される状態もない。
• このコードはスレッドセーフだ。ロックは必要ない。
• このコードは並列化可能だ。コードを変えることなく、各ステップのそれぞれを複数のスレッドで実行できる。
• 最後に、このコードはジェネリックだ。compositions は単なるセットであっても、XML であっても、あるいはデータベースの問い合わせ結果で
あってもいい。
関数型プログラムを、文によって明示的にプログラムの状態を書き換えていく命令型プログラムと比べてみよう。多くのオブジェクト指向プログラ
ムは命令型で書かれ、上に挙げた特長をひとつも持っていない。必要以上に複雑で、スレッドセーフではなく、並列化も一般化も難しい(関数型と
命令型のより詳しい比較を知りたければ2.6「for ループはどこにある?」(p. 51)を参照してほしい)。関数型言語の利点が知られるようになっ
てからしばらく経つが、Haskell のような純粋関数型言語はまだ世界を征服していないようだ。開発者にとって、普段の仕事を純粋関数型言語の枠
組みに当てはめるのは簡単なことではないからだ。Clojure が、これまでの関数型言語よりも開発者の興味を集めると考えるには4 つの理由がある
。
• 関数型言語の必要性はかつてないほど高まっている。多数のコアを持つハードウェアはもうすぐそこまで来ていて、関数型言語はその多数のコア
を活用するための明確な方法を提供する。関数型プログラミングについて詳しくは第5 章「関数型プログラミング」(p. 127)で触れる。
• 純粋関数型言語は、本当に変更が必要な状態をモデル化するのにはちょっとまどろっこしいところがある。Clojure は、ソフトウェアトランザク
ショナルメモリや参照(ref)、エージェント、アトム、そして動的束縛を使うことで、変更可能な状態を管理する構造的な方法を提供している(
ソフトウェアトランザクショナルメモリと参照については6.2「ref とソフトウェアトランザクショナルメモリ」(p. 159)、エージェントについ
ては6.4「非同期な更新にエージェントを使う」(p. 168)、アトムについては6.3「アトムを使った非協調的、同期的な更新」(p. 166)、動的束
縛については6.5「var でスレッドごとの状態を管理する」(p. 172)で説明する)。
• 多くの関数型言語は静的型を採用している。Clojure の動的型は、関数型言語を学び始めたばかりのプログラマにとっては近づきやすいだろう。
• Clojure からJava を呼び出す方法は関数型ではない。Java を呼び出すと、慣れ親しんだ変更可能な世界に入ることになる。これは、関数型言語
にまだ馴染んでいない初心者にとって、関数型のアプローチでは現実的な解法が思い浮かばないときに、恰好の避難所になるだろう。Java の呼び
出し方法は第3 章「Clojure からJava を使う」(p. 59)で説明する。
Clojure の、変更可能な状態へのアプローチは、明示的なロックを使わない並行プログラミングを可能にし、Clojure の関数型のコアを補完するも
のとなる。
Clojure は並行プログラミングを簡単にする
Clojure は関数型プログラミングをサポートすることで、スレッドセーフなコードを簡単に書けるようにしている。変更不可能なデータ構造は決し
て変わることが無いので、他のスレッドによってデータが壊されてしまう心配をしなくてよい。
けれどもClojure の並行プログラミングのサポートは、関数型プログラミングだけにとどまらない。変更可能なデータへの参照が必要になったら、
Clojure はそれをソフトウェアトランザクショナルメモリ(STM)で保護してくれる。STMはJava が提供するロックよりも高レベルのアプローチだ
。脆くてバグを持ち込みやすいロックを作る代わりに、共有される状態をトランザクションで保護することができる。プログラムはずっと書きやす
くなるだろう。多くのプログラマはデータベースの経験からトランザクションについてよく理解しているからだ。
例えば次のコードは、実際に動く、スレッドセーフなインメモリのデータベースを作成する。
(def accounts (ref #{}))
(defstruct account :id :balance)
ref 関数はトランザクションによって保護された、現在のデータベースの状態への参照を作成する。更新は簡単だ。次のコードはデータベースに新
たなアカウントを追加する。
(dosync (alter accounts conj (struct account "CLJ" 1000.00)))
dosync は、accounts への更新をトランザクションの中で実行するようにする。コードは自動的にスレッドセーフになる。これはロックよりも簡単
だ。トランザクションを使えば、どういう順序でどのオブジェクトをロックすべきか悩む必要はなくなる。トランザクションによるアプローチはま
た、よくあるケースではロックよりも良い性能を示す。例えば、読み出しがブロックすることがない、といった理由が考えられる。
上に挙げた例は単純すぎるように見えるかもしれないが、このテクニックは汎用性が高いもので、現場の問題を解決するのに使えるのだ。第6 章「
並行プログラム」(p. 157)で、並行プログラミングとClojure のSTM についてより詳しく説明する。
Clojure はJVM を歓迎する
Clojure からJava にアクセスするのはきわめて単純で直接的だ。どんなJavaAPI も直接呼び出すことができる。
(System/getProperties)
-> {java.runtime.name=Java(TM) SE Runtime Environment
... 後略...
Clojure はJava 呼び出しのためにさまざまな構文糖衣を用意している。ここでは細かいことには触れないが(詳しくは3.1「Java の呼び出し」
(p. 60)を参照)、次のコードにおいて、Clojure 版はJava 版よりも括弧もドットも少ないということに注目してほしい。
// Java
"hello".getClass().getProtectionDomain().getCodeSource()
; Clojure
(.. "hello" getClass getProtectionDomain getCodeSource)
Clojure はJava のインタフェースを実装したりJava のクラスを継承したりする簡単な関数を提供している。また、Clojure の関数はすべて
Callable でありRunnable である。したがって、Java のThread のコンストラクタにClojure の無名関数を渡すのは下に示すとおり簡単だ。
(.start (new Thread (fn [] (println "Hello" (Thread/currentThread)))))
| Hello #
#<...>というのはClojure がJava のインスタンスを表示する方法だ。Threadがインスタンスのクラス名、Thread[Thread-0,5,main] はインスタン
スをtoString した結果である。
(上の例で、新しいスレッドは終了するまで走るけれど、その出力がREPL のプロンプトと混じり合ってしまうことがある。これはClojure の問題
ではなく、単に複数のスレッドが1 つの出力に書き込むときに起こりうることだ。)
Java を呼び出すのはこのように簡単なので、Clojure ではJava をLisp っぽいラッパーで隠すのではなく、必要ならJava API を直接呼ぶことを奨
励している。
さて、Clojure を使うべき理由をいくつか見てきたので、いよいよコードを書いてみよう。
登録情報
- 出版社 : オーム社 (2010/1/26)
- 発売日 : 2010/1/26
- 単行本(ソフトカバー) : 304ページ
- ISBN-10 : 4274067890
- ISBN-13 : 978-4274067891
- Amazon 売れ筋ランキング: - 1,300,268位本 (本の売れ筋ランキングを見る)
- - 24,373位電気・通信 (本)
- カスタマーレビュー:
著者について
著者の本をもっと発見したり、よく似た著者を見つけたり、著者のブログを読んだりしましょう
カスタマーレビュー
私たちの目標は、すべてのレビューを信頼性の高い、有益なものにすることです。だからこそ、私たちはテクノロジーと人間の調査員の両方を活用して、お客様が偽のレビューを見る前にブロックしています。 詳細はこちら
コミュニティガイドラインに違反するAmazonアカウントはブロックされます。また、レビューを購入した出品者をブロックし、そのようなレビューを投稿した当事者に対して法的措置を取ります。 報告方法について学ぶ
-
トップレビュー
上位レビュー、対象国: 日本
レビューのフィルタリング中に問題が発生しました。後でもう一度試してください。
じっと見て、どうすればこうなるのか考えていると、小学生の頃に使っていた雨でグショグショにふやけて、ヨレヨレになった国語の教科書の記憶がよみがえり懐かしく思いました。
とてもはやく配達されてきました。
ありがとうございます。
入門書なのでごく簡単なガイドツアー的な本で、これを1冊学ぶと、Clojureのソースは書いたり読めたりします。関数型プログラミングの基礎も書かれているし、全く何も知らないという人が始めるには良い本です。一人で学習するのが心細いならば、ブログで学習ログを公開したり、Clojureの日本語のメーリングリストに登録して質問すればいいですよ。Clojure言語はまだ生まれて数年しか経ってない赤ちゃん言語なんですが、支持者が多く開発も活発です。だから、どんどん環境が便利になってきています。twitterでも利用されていたり、herokuでもサポートを開始されてきてたり、実用面でもどんどん活用される場面が増えていますので、学んでおいても面白い言語ですよ。
2013-4-6 補足
[...]
最近第二版の日本語版の発売がアナウンスされました。第二版は1.3準拠ですが、最新版1.5との関係は、1.0用の第一版で1.3を学ぶときのギャップは大きくないと思います。原著同士で比較する限り、今やclojureを使う上で標準的な道具になったleiningenを利用した使い方を書いてる点は変更してるが、基本的なところはあまり変わってないと思う。応用的なところは大幅な変化はあるようです。(clojure.contribの扱いが、1.2までと1.3以後で変わった[廃止]のは大きい。それ以外にもjavaライブラリの取り扱い関係とか)現在1.5用はこの世に出ていませんが、洋書ならJoy of Clojureが1.5準拠の第二版を準備中のようです。ただし、Joy of Clojureは初学者向けの本ではありません。
今からこの本を買うのなら第二版を待ったほうが賢明です。
Haskell、Erlang、Common Lisp、Scheme、Gaucheなどは、いずれも興味深いが、勉強しつつも、心のどこかで、実践で使うことは無さそうに感じていた。でもClojureなら、JDKにjarを1つ追加するだけで使え、まともな(ダサくない)GUIフレームワークも手に入るのだ。
本書では、言語仕様を学びながら、Antベースのビルド管理アプリを作る。これはデスクトップアプリではないが、マクロの威力やJavaライブラリとの接続性の良さを示す好例だ。
また、デスクトップアプリ(ゲーム)も作る。こちらでは、ピュアな(参照透明な)レイヤと副作用のレイヤとを分離した設計例を示している。
構成も良く、訳もまずまず安定しており(訳者はGaucheの発明者)、Clojureのコードがコンパクトに書けるおかげで同じコードが繰り返し掲載されても気にならない。
ただし、古いバージョンのClojureをベースにしている点は注意が必要。書籍の方も既に改訂版が出ている。
[2013-08-29]訳注に「Clojure1.1では、^ リーダマクロが非推奨になった」とある。しかしClojure1.2以降は、このリーダマクロで正解だ。1.1では「#^ を ^ で置き換える予定だけど、まだ正式採用じゃないよ」といったニュアンスで非推奨にしていたが、結局1.2で「^ が正式採用」となった。GitHubのchanges.txtに書いてある。
[2013-10-27]訳注に関するコメントは的外れだった。1.2で正式採用になったのは、(def ^:dynamic foo "hello")のように、メタデータの前に付けるリーダマクロのことだ。しかし訳注の意図は、(meta obj)のシンタックスシュガーとしての ^objが非推奨ということだった。1.1より前では、^objなんて書き方が使えたのね…。
2刷にはClojuie 1.2対応の修正が為されてるようです。
1刷の方で本の記述通りにいかないなと友人に確認したところ
友人の2刷では修正されていました。
かるく見比べたところ、細かい修正の他、訳注が増えるなどしていました。
1.1=>1.2で文法の変更もあるようですので注意してください。
内容について言えば章構成が微妙、日本語がおかしいなどあり、
訳本ですしある程度は仕方ないと諦めるしかないかもしれませんが
関数型言語の初心者には前提知識の不足と変な日本語が合わさって
無用の混乱を引き起こしかねないように思います。
とはいえ、Java VM上で動く関数言語というClojureの立ち位置は面白く
直接Java関数を呼べるなど、関数言語を試してようという方には悪くないと思います。
「Clojureでは、Lispの力を失わない限りにおいて、
できるだけLispっぽくないようにできる機会があれば
そちらを選択している」
LispとJavaが融合することで、プログラミングの
新たな可能性が出てきたと思う。
Clojureが出力するClassファイルから
Javaソースを逆アセンブリしてみるのも一興。
たとえば、例題の中でまだ説明していない"inc"という関数を使っている。この関数は、引数に1を加えた値を返す関数でLISPの経験がある人にとっては常識的な関数だ。入門書ではすでに解説した機能だけで例題を作るべきだ。
他にも、リスト(シーケンス)は基礎的なデータ構造であるにも関わらず、中盤で解説している事などから本書は既にLISP系の言語に習熟している人を対象にした本のように見える。
例題は言語仕様を示すためのごく短いコードが多数とソースコード管理システムの製作だけでつまらなかった。
だから、Clojureを学ぶことによって「Lisp系言語」への扉も開かれます。
本書はClojure同様にコンパクトですが、扱っている内容はClojureの全体像を掴むには十分です。
あとは、ClojureのREPL自身が教えてくれます(docを使いこなしましょう)。