كيف يمكنني القيام بـ 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

أستطيع أن أفهم لماذا لا يعمل ، لكن لا يمكنني إيجاد طريقة لتعديل حقول الهيكل. اي فكرة؟ شكرًا لك.

هل كانت مفيدة؟

المحلول

تريد استدعاء وظيفة الكاتب للبنيس عبر اسمه ، واسم الكاتب هو القائمة (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),

كما هو متوقع.

نصائح أخرى

تحفيز:

الهياكل هي منشأة منخفضة المستوى نسبيا. كان "السرعة" هدفًا مهمًا للتصميم. لا يدعم المعيار عدم التوجيه عبر وظائف الكاتب (كما قرأته). اليوم ، استخدم الإغلاق باعتباره الافتراضي ، ما لم يحتاج المرء إلى كفاءة أفضل للهياكل (قراءة أسرع وتكتب فتحات مع الهياكل في بعض الأحيان).

الأول - النمط:

لا تستخدم المتدرب ، استخدم Find-Symbol. حدد أيضًا الحزمة ، وإلا فإن Find-Symbol ستستخدم قيمة وقت التشغيل لـ * Package * كحزمة

الثاني - 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 بعض الهيكل) 42) ، يعتمد على توسعات setf المحددة التي توفرها DefStruct ، ولكن ليس على وظائف accessor setf المحددة.

قد توفر بعض تطبيقات LISP الشائعة وظائف الكاتب كامتداد غير قياسي لـ ANSI CL.

الحلول الممكنة:

أ) استخدام فئات الإغلاق ، فإن defclass تفعل ما تريد

ب) اكتب الكاتب وظائف نفسك

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

حاليا:

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

أعلاه ثم يعمل.

ج) (قيمة الفتحة setf)-ميزة أخرى غير قياسية لبعض التطبيقات.

في بعض تطبيقات LISP المشتركة ، لا يعمل هذا فقط لفصول الإغلاق ، ولكن أيضًا للهياكل:

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

لست متأكدًا مما إذا كان Allegro CL يدعم ذلك ، ولكن سيكون من السهل اكتشاف ذلك.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top