下記の記事を読んでいたら、Clojureというプログラミング言語の名前がちょこちょこと登場しているのが目に入り、少し調べてみることにした。
Clojureとは
Clojureとはどんな言語なのだろうか。Wikipediaをみてみる。
Clojure (発音は/'klouʒər/[2], クロージャー)はプログラミング言語であり、LISP系の言語の方言の一つである。関数型プログラミングのプログラミングスタイルでのインタラクティブな開発を支援し、マルチスレッドプログラムの開発を容易化する汎用言語である。
「LISP系の言語の方言」とある。LISPというのは名前だけ聞いたことがある程度だ。プログラミング言語で「方言」というと、SQL方言が真っ先に思い浮かぶが、LISPというのも標準語と複数の方言が存在する言語なのだろうか、とLISPについて調べ始める。なるほどLISPというのは歴史のある言語で、『計算機プログラムの構造と解釈』(SICP)という有名な教科書でも「Scheme」というLISP方言の言語が使われているようだ。
SICPは、プログラマ、というか計算機科学に関わるならば読んでおきたい書籍という扱いがされているようだ。日本語版のPDFでも700ページを超える重厚なもので、読み切るのは大変だろうが、とても勉強になりそうというのもまた確か。感想記事にはたくさんのはてブが付いている。いつか読んでみたい。
と、やっているとキリがないので、本題に戻って、Clojureを少し触ってみることに。しっかり環境構築をしようと思うと最初で挫折するので、手軽に試してみようと考え、公式ドキュメントで紹介されているREPLによる入門をやってみることにした。
Clojureの対話型実行環境「REPL」
様々な言語にREPLが存在するが、ClojureにもREPLがある。これは、ClojureのCLIツールに同梱されているので、簡単に使い始めることができる。Mac環境では、ClojureをHomebrewでインストールすれば使えるようになる。
$ brew install clojure $ clj Clojure 1.10.0 user=>
これで、REPLが立ち上がり、Clojureのプログラミングがでできるようになっている。下記の公式ドキュメントにしたがって、いくつか操作を試してみる。
パッとみて、括弧が激しく使われるなぁ、と思っていたら、REPLでは)
を入力したときに対応する(
がハイライトされるようだ。これで少しは助かる。
Clojureでは+
も関数
さて、手始めに足し算か、と思ったら、足し算からしてまず違う。演算子は前置記法で書く。
user=> (+ 2 3) 5
これは、関数と同じ書き方になるということでもある。というか、Clojureでは+
は立派な関数らしい。Javaがメインのプログラマにとって、演算子は通常のメソッドとは違う特別な存在だが、このClojureでは演算子も関数として定義されている。C++では演算子もオーバーロードできるし、プログラミング言語によって、同じような機能を持っているものの位置付けが違うのは面白いなと思う。
関数を定義するdefn
は「マクロ」
次は関数の定義。ここでは階乗の関数を定義している。
user=> (defn factorial [n] (if (= n 0) 1 (* n (factorial (dec n))))) #'user/factorial user=> (factorial 10) 3628800
defn
というのは関数ではなく、「マクロ」というものらしい。C言語から入っているので、マクロというと、#define
なのだけど、LISPのマクロは一味違うらしい。なるほどわからん。
if
は評価値を持つ「特殊形式」
また、面白かったものとして、if
がある。C言語やJavaで制御構造の一つをなしているif
が「文」を構成する(評価された値を持たない)のに対し、Clojureのif
は関数のように評価された値を持つ「式」ということになる*1。Clojureのif
は厳密には関数ではなく、「特殊形式」というものに当たるらしい。
Clojureのif
は、(if test then else)
という書き方をして、test
の評価値がnil
かfalse
でない場合はthen
を評価し、nil
やfalse
の場合はelse
を評価するというものになっている。関数的な言い方をすると、引数を3つとるわけだが、これはC言語やJavaの条件演算子Hoge ? Fuga : Piyo
に似ている。
CとJavaを学んだときは、「なんだよこれわかりにくいな、なんでこんなんあるんだ」と感じ、最近は、「これ使うと行数少なく書ける」くらいに感じていた条件演算子だったが、関数型の世界でのif
がこのような形になるのはなるほど自然で、にわかに条件演算子が由緒正しいものに思えてきた。
APIドキュメントを表示するマクロdoc
また、REPLには、doc
という便利な機能がある。(doc name)
とREPLで入力すると、name
で指定したもののAPIドキュメントが表示される。いくつか例を示す。
この機能があれば、REPLを使っていて関数などの使い方がわからなくなったときも、わざわざブラウザでドキュメントを見る必要がない。とても便利な機能だと感じた。
Clojureにおける「REPL駆動開発」
このdoc
をはじめとして、ClojureのREPLは単なる「入門用の遊び場」に止まらない機能を有している。そのためか、Clojureにおいては「REPL駆動開発」が書籍でも言及されているほどらしい。
感想
プログラミング言語は、C言語→Java(Stream API不使用)と学び始めて、それからある程度書いたことがあるのもPython、Ruby、JavaScript(TypeScript)あたりで、関数型言語は全く経験がない。Scalaも去年の8月に入門的レベルをほんの少しだけ触ってそのままになっていて、本格的に関数型らしいところまでたどり着かなかったので、今回は初っ端から関数型らしさを感じられて面白かった。
現在、約1年振りにJavaを仕事で書くことになり、前回は使わなかったStream APIも使い始めている。先日のJJUGのイベントで、GoFのデザインパターンの「振る舞いに関するパターン」をラムダ式で置き換えるというライブコーディングを見たこともあり、関数型プログラミングに対する関心が高まっている。オブジェクト指向もよくわかっていないのだけれど、せっかくStream APIを使えるのだから、関数型の考え方も取り入れながらプログラムが書けたらいいなと考えている。

- 作者: ハロルドエイブルソン,ジュリーサスマン,ジェラルド・ジェイサスマン,Harold Abelson,Julie Sussman,Gerald Jay Sussman,和田英一
- 出版社/メーカー: 翔泳社
- 発売日: 2014/05/17
- メディア: 大型本
- この商品を含むブログ (4件) を見る

- 作者: Stuart Halloway and Aaron Bedra,川合史朗
- 出版社/メーカー: オーム社
- 発売日: 2013/04/26
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (11件) を見る