user=> (def x 1)
user=> (def y 2)
user=> ^{:x x} [x y 3]
^{:x 1} [1 2 3]
評価は様々なコンテキストで行われ得る:
REPLでインタラクティブに
load
/ load-file
/ load-reader
/ `load-string`を通して読み込まれたフォームのシーケンスに対して
eval
を通してプログラマティカルに
Clojureのプログラムは式が組み合わさって成り立っている。スペシャルフォームやマクロで扱われない全てのフォームは、コンパイラによって値を作り出すために評価される。宣言やステートメントは存在しないが、副作用を起こす目的で式の評価を行い、値を無視することはある。全ての場合において評価は同じで、一つのオブジェクトがコンパイラに扱われ、評価され、値が戻される。式をコンパイルする必要がある場合はコンパイルされる。別のコンパイルのステップは存在せず、また定義された関数が解釈されることを心配する必要もない。 Clojure にインタプリタは存在しない 。
文字列、数字、 true
、 false
、 nil
はそれら自身として評価される。
以下の場合、シンボルは 解決される :
名前空間で修飾されている場合、値はそのシンボルが指すグローバルなvarの値となる。シンボルが指すグローバルなvarが存在しない、もしくはパブリックではない別の名前空間のvarを指している場合はエラーとなる。
パッケージ修飾されている場合、値はシンボルが指すJavaのクラスとなる。シンボルが指すクラスが存在しない場合はエラーとなる。
それ以外の場合は修飾がなく、以下の最初のものが適用される:
スペシャルフォームを指す場合、スペシャルフォームとして扱われ、そのように扱われる必要がある。
ローカルスコープにおいては (つまりは、関数の定義内においては)、ローカルバインディングを指すかをルックアップが行われる(例 関数の引数かletで束縛された名前)。ローカルバインディングを指す場合、値はローカルバインディングの名前となる。
現在の名前空間にシンボルに対応するクラスが存在するかを確認するためルックアップが行われる。存在する場合、シンボルはJavaのクラスオブジェクトを指すものとして扱われる。クラス名は通常クラスオブジェクトを意味するが、特別に扱われるフォームが存在することに注意 (例: '.' および 'new' )。
シンボルからvarへのマッピングの存在を現在の名前空間内でルックアップする。存在する場合、値はシンボルに指されるvarのバインディングとなる。
エラーとして扱われる。
シンボルにメタデータが含まれている場合、コンパイラがそれを使用する場合もあるが、結果の値には含まれない。
ベクター、セット、マップはそれぞれの中にあるオブジェクトが 評価された後の値 を含むvector、 (hash) set、 map を返す。ベクターの要素は左から右へ評価されるが、セットとマップについては評価の順番が定義されていない。メタデータマップについても同様。ベクター、もしくはマップがメタデータを持つ場合、評価後の メタデータマップが結果の値のメタデータとなる。
user=> (def x 1)
user=> (def y 2)
user=> ^{:x x} [x y 3]
^{:x 1} [1 2 3]
空のリスト ()
は空のリストに評価される。
空ではないリストはスペシャルフォーム、マクロ、関数への呼び出しとして扱われる。呼び出しの形式は (operator operands*) となる。
スペシャルフォームはコアな操作を行う、Clojureに組み込まれているプリミティブなフォームである。呼び出しの演算子がスペシャルフォーム名前に解決される場合、呼び出しはそのスペシャルフォームに対する呼び出しとなる。各フォームについては 特殊形式 で触れている。
マクロ はフォームを操作する関数で、文法の抽象化を可能にする。呼び出しの演算子がマクロ関数を指すグローバルなvarを指すシンボルである場合、そのマクロ関数が呼び出され、評価する前 の被演算子フォームを渡される。マクロの戻り値はその後、その場で評価される。
演算子がスペシャルフォームかマクロではない場合、呼び出しは関数に対するものとして扱われる。演算子、および被演算子(存在する場合)は両方とも左から右へと評価される。演算子の評価の結果がIFn(Clojureの関数を表現するインターフェース)にキャストされ,invoke()がそれに対して引数を渡した上で呼び出される。invoke()の戻り値が呼び出した式の値となる。関数呼び出しにメタデータが存在する場合、コンパイラに使用される場合があるが、結果の値には含まれることはない。 特殊形式 にあるように、スペシャルフォームとマクロは通常とは異なる引数の評価の仕方をする場合がある点に注意。
上記で触れられている以外のオブジェクトは全て自分自身に評価される。
(load classpath-resource …)
(load-file filename)
(load-reader reader)
(load-string string)
上記は単一のフォームの評価を記述している。各種ロードフォームはソースに含まれるフォームを逐次的に読み込み評価する。そのようなフォームは一般的にはグローバルな環境に対する副作用を伴い、関数の定義等を行う。
The loading functions occur in a temporary context, in which *ns*
has a fresh binding. That means that, should any form have an effect on that
var (e.g. in-namespace), the effect will unwind at the completion of the
load. load et al return the value produced by the last expression.
(eval form)
フォームの データ構造 (テキストではない!) を評価し、結果を返す。
(eval (list + 1 2 3))
-> 6