言語ゲーム

とあるエンジニアが嘘ばかり書く日記

Twitter: @propella (MF東京 8/3,4)

Clojure で遊ぶ

Clojure という言語がある。最近の言語はどれも関数型言語のアイデアを実用的に使えるようにするというのが目標に入っていると思うけど、Clojure は最も自然にそれを実現していて私はすごく気に入っている。という事で、実際にどんな感じなのか試してみた。

一番簡単なインストールと実行方法

ホームページにはインストールの方法が沢山書いてある。沢山ありすぎて正直うっとおしい。色々試して、結局素直に zip をダウンロードして適当な場所に置くだけというのが一番簡単だと分かった。具体的には http://clojure.googlecode.com/files/clojure-1.1.0.zip をダウンロードして中の clojure.jar を自分のディレクトリに置けば良い。実行は次のようにする。

$ java -jar clojure.jar
Clojure 1.1.0
user=> (+ 3 4)
7

これで clojure を電卓のように使える。プログラムをファイルに書いて実行するやり方も色々ある。まず、hello.clj というファイルがあるとして、

;; hello.clj
(javax.swing.JOptionPane/showMessageDialog nil "Hello, World!")

先ほどの clojure.jar の後ろにファイル名を書くとそのファイルが実行される。

$ java -jar clojure.jar hello.clj 
(Hello, World! というダイアログが表示される)

または LISP っぽく REPL の中でロードしてもよい。

$ java -jar clojure.jar
Clojure 1.1.0
user=> (load "hello")
nil

面白い事に、このロードも遅延評価でやっているらしく、括弧を多い目に書いたりするとプログラムが実行されてからエラーが出る。

Clojure はどのようにして Java を使っているか

私が今作ってるコンパイラの参考にしようと思って、Clojure のデータ構造について調べている。Clojure では わりと Java のデータをそのまま使って、無い奴だけ Clojure で実装している。型を知るのは type 関数を使う。ちなみに、シェルで (doc type) のようにすると関数の説明が出て来てとても親切。

;; typetest.clj
(print "What kind of object does Clojure use?\n\n")

(defn print-type
  [title obj]
  (println title ":" obj "=>\t\t\t" (type obj)))

(print-type "integer" 1)
(print-type "string" "Hello World!")
(print-type "float" 3.14)
(print-type "list" '(1 hello 3))
(print-type "symbol" 'hello-world)
(print-type "vector" '[1 hello])
(print-type "character" \c)
user=> (doc type)
-------------------------
clojure.core/type
([x])
  Returns the :type metadata of x, or its Class if none
nil
user=> (load "typetest")
What kind of object does Clojure use?

integer : 1 =>                   java.lang.Integer
string : Hello World! =>                         java.lang.String
float : 3.14 =>                  java.lang.Double
list : (1 hello 3) =>                    clojure.lang.PersistentList
symbol : hello-world =>                  clojure.lang.Symbol
vector : [1 hello] =>                    clojure.lang.PersistentVector
character : c =>                         java.lang.Character
nil
user=> 

気づいた事。リストの中身は同じ型じゃ無くて良い。何でも入れられる。ただし、まともなリストしかない。lisp で言う(hello . world) みたいなのは無い。また、例えばリストの実装について調べたい時は zip の中の src/jvm/clojure/lang/PersistentList.java を見れば良い。