Clojureでは、値に名前を結びつけることを_var_と呼びます。トップレベル(グローバル)のvarは、他の言語の定数に似ています。
トップレベルのvarは、defを使って定義します。
(def fingers 10)
fingers
;;=> 10
defnを使うと、0個以上の引数を取る関数を定義できます。これは、2つの数値を足し合わせる関数です。
(defn add [x y]
(+ x y))
この関数は2つの引数を取り、それらはベクター[x y]に置かれます。その後に、任意の数の式を書ける関数の本体が続きます。戻り値は、必ず本体の最後の式(+ x y)を評価した結果です。この式は、関数呼び出しを表すリストです。リストの先頭の要素が+関数であり、その後に続く要素xとyを引数として評価されます。
上で定義したadd関数も、同じように呼び出します。
(add 2 3)
;;=> 5
Clojureの関数や値は、定義した_後_にしか使えません。つまり、フォームは常に書かれた順に評価されます。
Clojureでは、空白文字は整形以外の意味を持ちません。
Clojureの関数とvarは、名前空間にまとめられています。名前空間は、関連する機能をひとつにまとめるもので、nsマクロを使って定義します。
(ns calculator)
(def pi 3.14)
(defn add [x y]
(+ x y))
Clojureでは、2種類のコメントを書けます。1行コメントは;で始めます。また、commentフォームは、(commentと)の間にあるすべての式を評価しないようにするために使います。
この演習では、お気に入りの料理本をもとに、最高のラザニアを作るためのコードを書いていきます。
ラザニアの調理にかかる時間に関わる、4つのタスクがあります。
ラザニアをオーブンに入れておくべき時間(分)を確認するために、変数expected-timeを定義します。料理本によると、オーブンに入れておくべき時間は40分です。
expected-time
;;=> 40
remaining-time関数を定義します。この関数は、ラザニアを実際にオーブンに入れておいた時間(分)を引数として受け取り、前のタスクで求めたオーブンに入れておくべき時間(分)をもとに、あと何分オーブンに入れておく必要があるかを返します。
(remaining-time 30)
;;=> 10
prep-time関数を定義します。この関数は、ラザニアに重ねた層の数を引数として受け取り、1層あたり2分かかるものとして、ラザニアの準備に何分かかったかを返します。
(prep-time 2)
;;=> 4
total-time関数を定義します。この関数は2つの引数を取ります。1つ目の引数はラザニアに重ねた層の数、2つ目の引数はラザニアをオーブンに入れておいた時間(分)です。この関数は、ラザニアの調理にかけた合計時間(分)を返します。これは、準備にかかった時間(分)と、その時点までラザニアがオーブンにあった時間(分)を足したものです。
(total-time 3 20)
;;=> 26