LoginSignup
5
4

More than 5 years have passed since last update.

Clojureのフォームを再確認する

Posted at

フォームとは

Clojureのプログラムはまずリーダがプログラムをフォームという単位毎に読み込み、それをClojureのデータ構造に変換し、そのデータ構造をコンパイルして実行します。

今回はClojureの基本パーツであるフォームがどういうものか、どういう種類があるかを一通り確認していきたいと思います。

フォームの種類一覧

フォーム
リスト (1 2 3), (str "hello" \space "world")
ブール値 true, false
Nil nil
文字 \a, \b
文字列 "hello"
シンボル user/foo, java.langString
数値 1, 2, 33
キーワード :tag, :doc
マップ {:name "Yuji" :gender "male"}
セット #{:ruby :clojure :javascript}
ベクタ [1 2 3]

リスト

リストは単なるデータであるが、関数呼び出しの構文としても使われる。最初の要素が関数名、その次の要素からはその関数の引数になる。

(+ 1 2 3)
;; => 6

(str "hello" "world")
;; => "helloworld"

ブール値とnil

Clojureにおけるブール値の規則は以下になります。

  • trueが真, falseが偽
  • falseの他に、nilもブール値が必要な場面では偽
  • false,nil以外は、ブール値が必要な場面では真
(if true "true" "false")    ;;=> "true"
(if false "true" "false")   ;;=> "false"
(if nil "true" "false")     ;;=> "false"
(if [] "true" "false")      ;;=> "true"
(if "hello" "true" "false") ;;=> "true"


文字

文字のリテラル表記は{letter}で、{letter}は文字そのものか文字の名前になる。

(str \h \e \l \l \o \space \w \o \r \l \d)
;; => "hello world"

文字列

文字列はダブルクォートで囲んで表記し、複数行にまたがることもできる

"hello world"
;;=> "hello world"
"hello
 world"
;; => "hello\n world"

シンボル

+, concat , java.lang.Stringといったフォームはシンボルといい、ものを名付けるのに使われる。例えば+は加算する関数の名前として使われている。

;; "hello"とプリントする関数をsay-helloというシンボルに束縛している
(def say-hello (fn [] (println "hello")))

(say-hello)
;;=> "hello"
;;=> nil

数値

数値はその値自身へと評価されるため、REPLに打ち込むとそれがそのまま返される。

57
;; => 57

算術演算子も以下のように使える。

(- 2 1)
;; => 1
(+ 2 1)
;; => 3
(* 2 2)
;; => 4
(/ 4 2)
;; => 2
(/ 22 7)
;; => 22/7 
(/ 22.0 7)
;; => 3.142857142857143
;; 商を求める
(quot 22 7)
;; => 3
;; 余りを求める
(rem 22 7)
;; => 1

キーワード

キーワードはシンボルに似ているが、コロン(:)で始まる。そして評価されると自分自身を返す。
自分自身を返すという特性上、キーワードはマップのキーによく使われる。

:tag
;;=> :tag
(def person {:name "yuji" :gender 'male'})
(person :name)
;; => "yuji"
(:name person)
;; => "yuji"

マップ

マップはキーと値のペアのコレクションである。マップはカーリブレース({})でくくって、リテラルで表記できる。
マップは関数としても動作する。キーをマップに引数として渡すと、対応する値があれば値を返し、なければnilを返す。

(def inventors  {:Lisp "McCarthy" :Clojure "Hickey"})
;; => #'user/inventors
(inventors :Lisp)
;; => "McCarthy"
(inventors :Ruby)
;; => nil

セット

セットはコレクションの各要素がユニークであることを保証したコレクションです。セットはシャープカーリブレース(#{})でくくって、リテラルで表記できる。
セットに対して値を与えると、対応する値があればその値を返し、なければnilを返す。

(def languages #{"Ruby" "Lisp" "Clojure"})
;; => #'user/languages
(language "Ruby")
;; => "Ruby"
(language "PHP")
;; => nil

ベクタ

ベクタはインデックスによってアクセスできるコレクションです。ベクタはスクエアブラケットでくくって、リテラルで表記できる。

(def language ["Ruby" "Lisp" "Clojure"])
;; => #'user/language
(language 0)
;; => "Ruby"
(language 1)
;; => "Lisp"
(language 9)
;; => IndexOutOfBoundsException   clojure.lang.PersistentVector.arrayFor (PersistentVector.java:107)

参考

プログラミング Clojure 第2版
Collections and Sequences in Clojure

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4