読者です 読者をやめる 読者になる 読者になる

Clojureの基本型

変数型はアトム(スカラ)とコレクション(ベクトル)に分類されますが、型は動的に決定されます。

アトム

数値

user=> 42
42

ブール型

user=> true
true
user=> false
false

文字列

user=> "Hello, world!"
"Hello, world!"

シンボル

「名前」を表すために使います。変数や関数などの名前として使い、値と結びつくことができます。シングルクォートで指定します。

user=> 'a
a

キーワード

シンボルに似ていますが、値と結びつく必要はありません。コロンで指定します。

user=> :hoge
:hoge

nil

ブール型にも似ていますが、nilはtrueでもfalseでもない特殊な「値がない状態」です。

user=> nil
nil
user=> (= nil true)
false
user=> (= nil false)
false

コレクション

コレクションは複数のアトムを集めて扱うための仕組みです。

list

シングルクォートを使っても同じことができます。

user=> (list 1 2 3)
(1 2 3)
user=> '(1 2 3)
(1 2 3)

リストの中にはどんな型のものでも入れることができます。

user=> '( :keyword (1 2 3) [4 5 6] #{7 8 9})
(:keyword (1 2 3) [4 5 6] #{7 8 9})

vector

listとほとんど同じ。違うのはClojureが動いているJava仮想マシンの内部でどう処理されているか。あと、listだと関数として実行することができますが、vectorは純粋なデータの集合体です。同図像性(homoiconicity)がないのですね。

user=> [1 2 3]
[1 2 3]

map

key/valueの組み合わせを記録しておくための型。

user=> {"x" 1 "y" 2 "z" 3}
{"x" 1, "y" 2, "z" 3}

どうもCommon Lispとか勉強した後だと「そんなのlistでやればいいじゃん」って思ってしまいますが、Clojureの背後にはJavaのmap型が見え隠れするので、そんなものかと思っておきます。key/valueごとに自動的にカンマが入るのですね。使い方は以下の通り。

user=> ({"x" 1, "y" 2, "z" 3} "y")
2
user=> ({"hoge" "moge", "fuga" "muga", "foo" "bar"} "hoge")
"moge"

他にも参照の仕方は数種類ある模様。

set

集合を表します。

user=> #{3 1 4 1 5 9 2 "hi" :x :y :z}
#{1 "hi" 2 3 4 5 :z :y :x 9}

違う型のアトムが混ざっても大丈夫っぽいですが、同じものが複数入るのはダメ。各要素に効率よくアクセスできるように、ハッシュを使って自動的に並べ替えられています。同じ型のアトムの集合であれば、ハッシュ状態と並べ替えた状態の二通りから選べます。

user=> (hash-set :3 :1 :4 :1 :5 :9 :2 :x :y :z)
#{:z :y :x :4 :5 :1 :3 :2 :9}
user=> (sorted-set :3 :1 :4 :1 :5 :9 :2 :x :y :z)
#{:1 :2 :3 :4 :5 :9 :x :y :z}