ほとんどの実装では(make-instance 'struct-type)
、その型のコンストラクター関数を定義したかどうかに関係なく、 を使用して構造体を作成できます。これは Allegro や ABCL では機能しませんが、これらの実装では を使用して読み取り時に構造体を作成できます#S(struct-type)
。これにより、型名をシンボルとして指定すると、実行時に構造体を構築する別の方法が必要になると思います。
3 に答える
構造とオブジェクトの作成を混在させないでください。、および提供されたシンボルが に渡されるように定義された標準make-instance
は、再帰します。standard-class
symbol
find-class
make-instance
そのmake-instance
ため、名前付き構造体型を拡張するストック実装は準拠しておらず、それに依存しているコードも準拠していません。
次に、構造体に標準のコンストラクターがある場合にのみ正しく機能するように#S
指定されているため、そこにはあまり魔法が残っていません。
この制限があるため、構造体名と連結された#S
名前のシンボルをインターンしmake-
、その後にキーワード引数リストを続けることで、自分で実装できます。
しかし、ここでも、実装に依存する詳細がヒットします。コンストラクターがない場合について尋ねます。これは in を意味:constructor nil
しdefstruct
ます。コンストラクター引数を指定しないということは、デフォルトのコンストラクターがあることを意味することに注意してください。実装には、オプション (またはパラメーターなしのコンストラクターとスロット アクセサー) に関係なく作成される非表示の標準コンストラクターmake-load-form-using-slots
、拡張された#S
、およびおそらくリテラル構造の読み込みを最適化するための (作成するフォームとは対照的に) 内部簿記を含めることができます。 1 つ)make-load-form
の構造体の特殊化によるファイルのコンパイル。
考えられる解決策を 1 つ考えましたが、これはちょっとハックです。リーダー マクロは機能しますが、#S
ABCL と Allegro がそれをどのように実装しているかはわかりません (完全に実装の内部にあり、Lisp で定義されていない可能性があります)。少なくとも文字列を生成し、プログラムでリーダー マクロ関数を呼び出すことができます。 :
(defun make-struct-from-type (type-name)
(with-input-from-string
(s (format nil "(~A::~A)"
(package-name (symbol-package type-name))
(symbol-name type-name)))
(funcall (get-dispatch-macro-character #\# #\S)
s #\S nil)))
ただし、これは他の実装では機能しない場合があります。SBCL はバインドされていないことに不満を持っsb-impl::*read-buffer*
ているため、リーダー マクロが通常のコンテキストで呼び出されていると実装に思わせるには、もう少し工夫が必要になる場合があります。
make-
これにより、デフォルトの接頭辞なしで名前が付けられた場合でも、デフォルトのコンストラクターが呼び出されます。