(rontolisp) docs
← プロトコル、レコード、型

defrecord

(defrecord Name [fields...] Protocol (method [target & args] body...) ...)

レコードを定義します。型タグ付きのマップです。すべてのマップが使うエントリ表を (:C%RECORD tag fields table class) で包むため、マップ動詞はそれを通して読みます (get・contains?・keys・vals・count・seq はエントリを読み、 assoc・update・conj・merge は表を組み直してタグを保ち、dissoc は宣言 フィールドが全部残る間はレコードを保ち、そうでなければオラクル同様プレーンな マップに落ちます)。= は2つのレコードをタグとエントリで比べ、プレーンなマップ と等しくなることは決してありません。コンストラクタは2つで、マングルされた関数に lower されます。位置指定の ->Name(数が違うとシグナル)とマップからの map->Name(欠けたフィールドは nil、余分なエントリは保持)。(Name. ...) は ->Name に書き換わります。インラインのメソッド本体にはフィールドがローカルとして 見え、インスタンス呼び出しはインラインのメソッドと宣言フィールドに届きます (.name)。名前はファイル全体の事前走査に参加するため、コンストラクタ呼び出しは 定義より前に書けます。

レコードはオラクル同様リテラルで印字されます。#user.R{:a 7} のように、定義した 名前空間(- は _ と綴る)と名前を並べ、宣言フィールドを先に置きます。リテラルは ソースでも read-string/read でも読み戻せます。 #ns.Name{:k v ...} は評価しない本体からレコードを組み(欠けた フィールドは nil、余分なキーは保持)、#ns.Name[v ...] は位置指定で組みます(数が 違えば拒否)。クラスはプログラムが定義したレコードでなければなりません。ドットのない #Name{...} はタグ付きリテラルで、オラクル同様拒否されます (No reader function for tag Name)。

仕様との差異:レコードの str もリテラルを綴ります。オラクルは user.R@<hash> を返します。