インターンを使用するときに、structのアクセサにsetfを行うにはどうすればよいですか

StackOverflow https://stackoverflow.com/questions/3641509

  •  30-09-2019
  •  | 
  •  

質問

そうしたいです。 setf 特定の変数に応じて、構造体の異なるフィールド。次のアプローチを使用することにしました。

フィールドのアクセサー名で文字列を生成します。

(setq my-string (format nil "STRUCT-ESTADISTICAS-NUM-~S" x))

そして、funcallでインターンを使用します:

(funcall (intern my-string) *estadisticas*)

この呼び出しは、構造体のフィールドの正しい値を返しますが、私が試してみると setf この価値を変更するために、それは次のように不満を言います

(setf (funcall(intern my-string) *estadisticas*) 0)
Error: `(SETF FUNCALL)' is not fbound

なぜそれが機能しないのか理解できますが、structのフィールドを変更する方法を見つけることができません。何か案が?ありがとうございました。

役に立ちましたか?

解決

あなたはその名前を介して構造体の作家関数を呼び出したいと思っています、そして、作家の名前はリストです (setf accessor-name);それで

(funcall (fdefinition (list 'setf (intern my-string))) 0 estadisticas)

編集:

コードの残りの部分を見ていないので、何がうまくいかなかったかを推測するのは難しいです。 SBCLでは、これは私にとってうまくいきます:

(defstruct point x y)
(let ((point (make-point :x 1 :y 2)))
  (funcall (fdefinition (list 'setf (intern "POINT-X"))) 10 point)
  point)

上記は評価します

#S(POINT :X 10 :Y 2),

予想通り。

他のヒント

動機:

構造は比較的低レベルの施設です。 「スピード」は重要な設計目標でした。作家関数を介した間接は、標準によってサポートされていません(私が読んだように)。現在、構造の効率が向上する必要がある場合を除き、デフォルトとしてClosを使用します(構造を持つスロットの読み取りと書き込みがより速くなります)。

First -Style:

インターンを使用しないで、Find-Symbolを使用してください。また、パッケージを指定します。それ以外の場合は、Find-Symbolはパッケージとして *パッケージ *のランタイム値を使用します

2番目 - defstruct

ANSI CL標準を正しく読むと、DefStructがDefclassのようにスロットのライター関数を作成するわけではありません。

CL-USER 24 > (defstruct foo bar baz)
FOO

CL-USER 25 > #'(setf foo-bar)

Error: Undefined function (SETF FOO-BAR) in form (FUNCTION (SETF FOO-BAR)).

したがって、そのような名前(setf foo-bar)を構築し、その機能を見つけようとすると、defstructによって定義された関数がないため、失敗します。

ユーザーコード(SETF(FOO-BAR Somettruct)42)では、Defstructによって提供される定義済みのSETF拡張に基づいていますが、定義されたSETFアクセサーズ関数には基づいていません。

いくつかの一般的なLISP実装は、ANSI CLの非標準拡張としてライター機能を提供する場合があります。

可能な解決策:

a)クロークラスを使用し、Defclassはあなたが望むことをします

b)作家の機能を自分で書く

(defun (setf foo-bar) (new-value struct)
   (setf (foo-bar struct) new-value))

今:

(funcall (fdefinition '(setf foo-bar)) 300 *foo*)

上記は機能します。

c)(setf slot-value) - いくつかの実装のもう1つの非標準機能。

一般的なLISPのいくつかの実装では、これはクロスクラスだけでなく構造にも機能します。

(setf (slot-value some-struct 'bar) 42)

アレグロCLがそれをサポートしているかどうかはわかりませんが、それは簡単に見つけることができます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top