Clojure

評価

評価は様々なコンテキストで発生する

  • REPLでのインタラクティブな実行

  • load / load-file / load-reader / load-string を介して、ストリームから読み取ったフォームのシーケンスでの実行

  • eval を介したプログラムによる実行

Clojureプログラムは式で構成されています。特殊形式またはマクロによって特別に扱われないすべてのフォームは、コンパイラによって式とみなされ、評価されて値を生成します。宣言やステートメントはありませんが、場合によっては式が副作用のために評価され、その値が無視されることがあります。すべての場合において、評価は同じです。コンパイラは単一のオブジェクトを考慮し、評価し、その結果を返します。式をコンパイルする必要がある場合は、コンパイルされます。個別のコンパイルステップはなく、定義した関数が解釈されていることを心配する必要もありません。Clojureにはインタプリタはありません

文字列、数値、文字、truefalsenil、キーワードはそれ自体に評価されます。

シンボルは解決されます

  • 名前空間修飾されている場合、値はシンボルによって名前が付けられたグローバルvarのバインディングの値です。シンボルによって名前が付けられたグローバルvarが存在しない場合、または参照が別の名前空間の非公開varへの参照である場合はエラーです。

  • パッケージ修飾されている場合、値はシンボルによって名前が付けられたJavaクラスです。シンボルによって名前が付けられたクラスが存在しない場合はエラーです。

  • それ以外の場合は、修飾されておらず、次のうち最初が適用されます

    1. 特殊形式の名前である場合、特殊形式と見なされ、それに応じて使用する必要があります。

    2. ローカルスコープ(例:関数定義またはletフォーム内)にある場合、ローカルバインディング(例:関数引数またはletバインディングされた名前)の名前であるかどうかを調べるためのルックアップが実行されます。そうである場合、値はローカルバインディングの値です。

    3. 現在の名前空間で、シンボルからクラスへのマッピングがあるかどうかを調べるルックアップが実行されます。そうである場合、シンボルはJavaクラスオブジェクトの名前であると見なされます。通常、クラス名はクラスオブジェクトを示すことに注意してください。ただし、特定の特殊形式(例:.およびnew)では特別に扱われます。

    4. 現在の名前空間で、シンボルからvarへのマッピングがあるかどうかを調べるルックアップが実行されます。そうである場合、値はシンボルによって参照されるvarのバインディングの値です。

    5. エラーになります。

シンボルにメタデータがある場合、コンパイラによって使用される可能性がありますが、結果の値の一部にはなりません。

ベクター、セット、マップは、それらに含まれるオブジェクトの評価された値を内容とするベクター、(ハッシュ)セット、マップを生成します。ベクター要素は左から右に評価され、セットとマップは未定義の順序で評価されます。メタデータマップも同様です。ベクターまたはマップにメタデータがある場合、評価されたメタデータマップは結果の値のメタデータになります。

user=> (def x 1)
user=> (def y 2)
user=> ^{:x x} [x y 3]
^{:x 1} [1 2 3]

空のリスト()は、空のリストに評価されます。

空ではないリストは、特殊形式、マクロ、または関数への呼び出しと見なされます。呼び出しは、(演算子 オペランド*) の形式を持ちます。

特殊形式は、Clojureに組み込まれたプリミティブであり、コア操作を実行します。呼び出しの演算子が特殊形式の名前に解決されるシンボルである場合、その呼び出しはその特殊形式への呼び出しです。特殊形式で個別に説明されています。

マクロは、フォームを操作する関数であり、構文の抽象化を可能にします。呼び出しの演算子がマクロ関数であるグローバルvarの名前であるシンボルである場合、そのマクロ関数が呼び出され、評価されていないオペランドフォームが渡されます。マクロの戻り値は、その場所で評価されます。

演算子が特殊形式でもマクロでもない場合、呼び出しは関数呼び出しと見なされます。演算子とオペランド(存在する場合)の両方が左から右に評価されます。演算子の評価の結果はIFn(Clojure関数を表すインターフェース)にキャストされ、評価された引数を渡してinvoke()が呼び出されます。invoke()の戻り値が呼び出し式の値です。関数呼び出しフォームにメタデータがある場合、コンパイラによって使用される可能性がありますが、結果の値の一部にはなりません。特殊形式とマクロは、特殊形式のエントリで説明されているように、引数の通常とは異なる評価を行う可能性があることに注意してください。

上記で説明した以外のオブジェクトは、それ自体に評価されます。


(load クラスパスリソース …​)
(load-file ファイル名)
(load-reader リーダー)
(load-string 文字列)

上記は、単一のフォームの評価について説明しています。様々なロードフォームは、ソースに含まれるフォームのセットを順番に読み取り、評価します。このようなフォームのセットは通常、グローバル環境に副作用があり、関数などを定義します。

ロード関数は一時的なコンテキストで発生し、その中で*ns*は新しいバインディングを持ちます。つまり、フォームがそのvarに影響を与える場合(例: in-namespace)、ロードの完了時に影響は元に戻ります。loadなどは、最後の式によって生成された値を返します。


(eval フォーム)

フォームのデータ構造(テキストではない!)を評価し、結果を返します。

(eval (list + 1 2 3))
-> 6