Michael Fogus氏とChris Houser氏の共著The Joy of Clojureは、読者にClojureの文法を教えるだけでなく、Clojureらしいコードを流暢に書く方法を示そうとしている。この本は、関数型の視点からプログラミングの問題にアプローチする方法を教えてくれる。またClojureのコードをエレガントで効率的にするためのLispの手法も習得できる。
著者によれば、Clojureでのプログラミングには"正しい方法"がある。この本は問題解決を行うときの"Clojureの考え方”を紹介するのが目的だ。また、読者はプログラミングの方法を変更する必要があるのはいつなのか認識することができる。並列性や相互運用性、性能などのソフトウエアの世界の難しい問題に取り組むことで、これらのことを教えてくれるのだ。
この本の出版元であるManningは第9章“Exploring Clojure multimethods with the universal design pattern”の抜粋をInfoQに独占的に提供してくれた。
またInfoQの読者は40%オフで Joy of Clojureをコード“infoq40”を利用することで40%オフでこの本を入手できる。
InfoQは著者であるMichael Fogus氏とChris Houser氏にインタビューを行い、この本とClojureについて話を聞いた。
InfoQ: お2人自身のことについて少し教えてください。どうしてClojureの本を書くことになったんですか。
Chouser: Fogusがこの本の共著者にならないかと誘ってくれたんです。断る理由はありませんでした。
Fogus: Chouserは謙遜しています。Chouserがいなかったら"Clojureの楽しみ"は存在しなかったというのが本当のところです。本を書くのは難しいことで1人で書くことも、書くことができるすごい著者がいることも想像できませんでした。私は単なる普通のプログラマで、生まれた当初のClojureを見つける幸運に恵まれただけでした。本を書くことは生涯の夢というわけではありませんでしたので、Manningから話があったときも本当は書きたいとは思っていなかったんです。実際、一度は断りました。しかし、Chouserと一緒に仕事ができる可能性があったので断らなかったんです。ChouserはClojureを食べ、Clojureで呼吸しているような男ですからね。Chouserとの共同作業は本当に刺激的でした。私たちの本のすべての読者の中でも私が一番学んだのは間違いありません。
InfoQ:この本の内容を簡単に紹介してくれませんか。Clojureの最も強力な価値とはなんでしょう。他のJVMの言語とどのように競合するのでしょうか。
Chouser: ClojureはJVMの言語の中でもユニークです。というのは、Clojureはなじみのある概念が言語の各構成要素まで落とし込まれ、それを利用者が自由に再構成できるからです。多くの中からひとつ例を挙げると、Clojureは継承や多態性のような従来のオブジェクト指向の特徴を備えていますが、これらの特徴はクラスやその他の概念とは無関係に提供されます。つまり、必要に応じてこれらの特徴を再結合することもできますし、分離したままにしておけば、従来とは違った方法でこれらの特徴を組み合わせることで驚くべき力を得ることができます。こういう考え方は、Clojureのオブジェクトの扱い方だけでなく、並列性やコレクション、関数、そしてこの言語の文法にまで浸透しています。
Fogus:OOPの経験があるプログラマにClojureを説明するのは、実は難しいんです。Chouserが言うように、継承や多態性、カプセル化といった概念は"クラス"と強く結びついています。この事実はClojureを学ぶときには大きな壁になりがちです。
目に触れる機会が多い他のJVMの言語ではJavaのようなX(XにはScalaやGroovyなどが入ります)を書けます。しかしClojureはとても独特で今までのソフトウエアの書き方を再考しなければなりません。
InfoQ: Clojureの導入についてはどう考えていますか。今までのところ、オープンソースプロジェクトのコミュニティやエコシステムは形成されているのでしょうか。
Chouser:ノースカロライナで開かれた第1回目のClojure Conjカンファレンスから戻ってきたとき、コミュニティは単に形成されているだけでなく、多様で成長していて、賢く有益な人々であふれていました。そして、これらの人々は現実のプログラミングの要請を満たすために
Clojureを使うことに関心のある人がほとんどでした。このような状況ですので、さまざまなオープンソースプロジェクトが自然と生まれました。これらのプロジェクトの成果の多くはClojure Contribにあります。Clojure Contribも大きなClojureプロジェクトの一部分です。その上、すべてのJavaライブラリがそのままClojureから直接利用できるので、githubやgoogle codeでも関連するプロジェクトが多く生まれています。
Fogus: Chouserが骨子を説明してくれましたが、私もひとこと付け加えたいです。Clojureは他の一般的な言語と比べれば相対的に若いですが、エコシステムの成長には驚くべきものがあります。Richでさえ、このような形でClojureが飛び立つとは想像できなかったのではないかと思います。
InfoQ: バージョン1.2の新しい機能は何ですか。そしてChris、バージョン1.3に向けてのさまざまな改善の中で、あなたが性能改善を行っていると聞きましたが本当ですか。
Fogus: このスライドhttp://fogus.me/static/preso/clj1.2+ にはClojure 1.2の変更の概要が書いてあります。
Chouser:これはとても素晴らしい要約です。もっと詳しい内容は、公式の"Clojure 1.2の変更点": http://github.com/clojure/clojure/blob/1.2.x/changes.txtに書かれています。
私はClojure 1.3の性能改善には関わっていません。しかし、Rich Hickeyはこの問題に一生懸命取り組んでいます。Richが行っている変更の中には、Javaと同じくらいの性能が求められる領域でClojureを使っている人なら誰でも、本当にすごいと思えるものもあります。1.3のリリースはまだ先になるかもしれませんが、アルファ2はすでに性能改善がなされています。それだけでなく、ほとんどのClojureのプログラムが変更なしで性能が良くなります。名前付き関数の呼び出しは早くなっています。そして、Javaの数値型がタイプヒンティングを使わずに利用できる場面が多くなったため、タイトなループでの数値処理でも最適な性能が発揮できます。
InfoQ: Michael、あなたは最近、コミュニティのClojureのコーディング標準に賛成していましたね。あなたの主張はどんなものですか。現在のClojureプロジェクトではどんな取り組みがなされていますか。
Fogus:この件に関しての私は冗談で記事を書きました。誰が個人的な審美的趣味をプロジェクトに持ち込んでも私は気にしません。私が唯一考えていたことは、"コミュニティの標準"から離れすぎてしまうと、貢献者になる可能性が遠ざかってしまうことでした。
Chouser: パス。 :-)
InfoQ: Clojureをプロジェクトで初めて使うチームに何かアドバイスをお願いします。また、Javaの専門家の間にClojureを紹介してください。気をつけるべき主な落とし穴は何でしょう。“ベストプラクティス”はどんなものですか。
Chouser: 敏感になることが必要です。ほとんどすべてのプログラマや多くのマネージャは人生のある時点でLISPを使ったことがあるか、使わざるを得ない状況になったことがあると思います。今まで使ったことのないのなら、何か理由があるはずです。Clojureのすごさを声高に主張したり、逆にすごさに反抗したりしても仕事でClojureを使う機会を得易くはなりません。その代わりに、私が勧めるのは(丸括弧、高階関数などに)慣れていないためにチームが経験する不快な思いや
(高いレベルの抽象の簡潔さや不変性、並列性のサポートなど)Clojureが提供する利便性の両方に共感することです。
Fogus: Clojureの導入は難しいでしょう。それには多くの理由がありますが、いずれもClojureのエレガントさや利点とは関係ありません。また、Clojureの学習曲線の始めにある隆起はとても高いです。しかし、プログラミング言語が与える認知的負荷は初心者の感じ方を基準にしては
測れないことを私たちは知っています。友人や同僚を支援して最初の障害を超えましょう。最終的にClojureを使えるようになると、その瞬間はとても美しいですから。
Chouser: Clojureを使うことを計画したら、上手く使うことが重要です。Clojureも他の言語と同じようにメンテナンスの悪夢が簡単に生まれます。なので、Contribの中やClojureそのものにも含まれている良いコードを読んで、優れたソリューションを設計する方法について書かれた本を読み(興味があるならおすすめの本が1冊あります)、グループフォーラムでコードや設計の問題を質問することを恐れてはなりません(http://groups.google.com/group/clojure)。
Fogus: さらにFreenodeの#clojureのIRCチャンネルはいつも親切なClojurianがたくさんいます。
InfoQ: “Clojure vs. Scala”の主要な論点のひとつはScalaの方が開発者が慣れているOOのパラダイムを利用できるということです。一方でClojure"純粋な関数型"です。この件についてコメントをいただけますか。
Chouser: ええ、最もな質問です。下はこの件を知るために必要なすべてのことが含まれている手書きの図です。
| 良い | 悪い | --------+-------+-------+ Scala | | O_o | --------+-------+-------+ Clojure | ^_^ | | --------+-------+-------+
Fogus: フーム。良いと悪いの組み合わせの数はいくつですか。混乱してしまうなあ。
Chouser: でも直接的な"これ vs. あれ"プログラミング言語論争はほとんど利益がありません。しかし私も時々、このような論争に引き入れられることがあります。ClojureもScalaもJVMを利用するためにとても実践的な決定をしています。これは、実用主義を示す
ものであり、実用主義は普通のプログラミングの仕事をやり遂げようとしている誰もを安心させるべきものです。Javaクラスの実装や、新しいクラスとインターフェイスの定義、Javaコードの呼び出し、Javaコードからの呼び出し、データとコードの連携、多態性、そして、高階関数、不変コレクションや不変ローカル変数など、これらすべてをClojureもScalaもサポートしています。したがって、"関数型"や"オブジェクト指向"という言葉から多くを読み取りすぎてはなりません。
でも、新しい言語を選択することで自分が使っている言語の複雑性に目を向けようとしている人は誰でも応援したいです。ある機能を使うことが必要以上の複雑さをもたらすことがどのくらいありますか。このような複雑さに耐えるのはどのくらい楽なことでしょうか。もちろん、意図した以上の価値を親しみやすさ
に求めてはなりません。
Fogus: Rich Hickeyは、"エレガントさと親しみやすさは直交する"、と言っています。
InfoQ: この本に書かれているように、Clojureの大原則は不変性です。この概念はJavaプログラマにとっては何から何まで先進的です。不変性について教えていただけますか。
Chouser: 初めて聞いたときは私も確かに先進的だと思いました。つまり、何も変更できないでどうやって何かを成し遂げるのか、と思ったんです。でも、ある特定の文脈では、私たちのほとんどはこの概念に既になじみがあります。例えば、関数の内部でその関数の引数を変更するのは常に悪いことだということは誰もが知っています。
function sum(an_array) { // please don't change an_array here! }残念なことに普通、命令型言語はどんな場合でも変数の変更を回避する仕組みを提供しません。しかし、下の場合はan_arrayもxも変更できません。accumulatorだけが更新できます。
function sum(an_array) { var accumulator = 0; an_array.forEach( function(x) { accumulator += x; // why is it ok to change accumulator? }); return accumulator; }forEachが少し違った動きをして、an_arrayの各要素を取り出すだけでなく、合計値も算出していますが何か問題があるでしょうか。そして、forEachが終わると単純に最終の合計値を返します。では新しいバージョンのforEachである"forAll"を呼んでみましょう。
function sum(an_array) { var accumulator = an_array.forAll( 0, // start with zero function(running_total, x) { return running_total + x; // add to the total } ); return accumulator; }これで、言語がサポートしていれば、ローカル変数を変更せずに処理をすることが可能になります。Clojureの場合はローカル変数の変更が禁止できるだけでなく、それを完結にとても自然に実現できます。上の"forAll"はClojureでは"reduce"と呼ばれます。最終的な合計算出は下のように書き換えることができるでしょう。
(defn sum [an-array] (reduce (fn [running-total x] (+ running-total x)) ; add to the total 0 ; start with zero an-array)) ; array to iterate overあるいは単に、
(defn sum [an-array] (reduce + 0 an-array))Clojureはローカル変数の不変性を強制し、このようなコーディング方法がうまくいくようなリッチなコレクションを提供します。したがって、コレクションを構築したり、更新したりするのは合計値を算出するのと同じくらい自然に実現できます。
それほど先鋭的ではないんですよ。 :-)
InfoQ: Clojureを発見したばかりの人がこの本から得られるもっとも価値あることは何だと思いますか。次のレベルに進みたい熟達したClojureプログラマにとってはどうでしょう。
Chouser:今まで命令型のソリューションを考えることだけにキャリアを費やしてきたのなら、少し力を入れて上のようなソリューションを考えられるように脳を鍛え直すような実践をすることです。同様に各種の
プログラミングの問題に対するClojureのアプローチは少しなじみのないものかもしれません。この本は関数型言語についてだけでなく、分割や不変コレクション、遅延シーケンス、マクロ、オブジェクトの扱いなども説明しています。この本はClojureの完結な紹介から始まっていますが、
もっとも上級のClojurian以外はClojureを利用した問題解決について何かを学ぶことができるでしょう。
なので、この本を読むことで毎日直面しているプログラミング上の問題を考え、解決するための新しい方法を身につけられるといいと思います。
Fogus:Chouserが例を挙げて示してくれたように、私たちが本で示したテクニックの多くはどんなプログラミング言語にも適用できます。しかし、そのようなことを規約ではなく言語レベルで実現することの利点があります。関数型言語はある型や形式の中では、すべての主流言語とは言わないまでもほとんどの言語を(最終的には)包摂しています。将来を見通したキャリアのために関数型プログラミングの"なぜ"と"どうやって"を理解しておくことは重要だと思います。
ここInfoQでもClojureについてさらなる情報を得ることができる。