سؤال

ولدي الصورة في التعبير منضم إلى متغير في اللثغة المشتركة:

(defvar x '(+ a 2))

والآن أريد أن إنشاء دالة أنه عندما دعا، ويقيم التعبير في نطاق الذي تم تعريفه. لقد حاول هذا:

(let ((a 4))
  (lambda () (eval x)))

و

(let ((a 4))
  (eval `(lambda () ,x)))

ولكن كلا من هذه تخلق مشكلة: وحدة التقييم تقييم رمز على أعلى مستوى، لذلك لا يمكن التقاط المتغيرات الواردة في التعبير. علما بأنني لا يمكن وضع نموذج LET في EVAL. هل هناك أي حل؟

وتحرير: حتى إذا لم يكن هناك حل للمشكلة EVAL، وإلا كيف يمكن أن يتم ذلك

وتحرير: كان هناك سؤال حول ما بالضبط وأنا أحاول القيام به. وأنا أكتب مترجم. أريد لقبول الصورة في التعبير مع المتغيرات مغلقة في البيئة المعجمية حيث يتم تعريف التعبير. قد يكون في الواقع أفضل لأنه يكتب كما ماكرو.

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

المحلول

وتحتاج إلى إنشاء التعليمات البرمجية التي لديها ارتباطات اللازمة. التفاف LET حول التعليمات البرمجية وربط كل متغير كنت تريد أن تجعل متاحة في التعليمات البرمجية:

(defvar *x* '(+ a 2))

(let ((a 4))
  (eval `(let ((a ,a))
           ,*x*)))

نصائح أخرى

وCLISP تنفذ امتدادا لتقييم النموذج في بيئة المعجمية. من حقيقة أنه هو امتداد، وأظن أنك لا تستطيع أن تفعل ذلك بطريقة متوافقة مع المعيار.

(ext:eval-env x (ext:the-environment))

http://clisp.cons.org/impnotes.html#eval- البيئى .

ما هي المشكلة الفعلية التي تريد حلها؟ على الأرجح، كنت في محاولة لمعالجة ذلك بطريقة خاطئة. الارتباطات المعجمية هي للأشياء التي تظهر مفرداتيا ضمن نطاقها، وليس للأشياء عشوائية تحصل عليها من الخارج.

وربما كنت ترغب في إغلاق الديناميكي؟ لا يوجد شيء من هذا القبيل في اللثغة المشتركة، على الرغم من أنه يفعل في بعض لهجات اللثغة (مثل بيكو اللثغة، بقدر ما أفهم).

لاحظ أنك <م> يمكن القيام بما يلي، وهو ما يماثل:

(defvar *a*)
(defvar *x* '(+ *a* 2))  ;'

(let ((a 10))
  ;; ...
  (let ((*a* a))
    (eval *x*)))

وأنصحك أن تفكر مليا في ما إذا كنت تريد حقا هذا، وإن كان.

ومن الممكن استخدام COMPILE لتجميع التعبير إلى وظيفة ومن ثم استخدام PROGV إلى FUNCALL وظيفة جمعت في بيئة حيث يتم تعيين المتغيرات بشكل حيوي. أو، بشكل أفضل، استخدم COMPILE لتجميع التعبير إلى وظيفة أن يقبل المتغيرات.

وترجمة يقبل تعريف الدالة كقائمة وتحويله الى وظيفة. في حالة SBCL، يتم تصنيف هذه الوظيفة إلى رمز الجهاز وسيتم تنفيذ بكفاءة.

والخيار الأول (باستخدام تجميع وprogv):

(defvar *fn* (compile nil '(lambda () (+ a 2)))
(progv '(a) '(4) (funcall *fn*))
=>
6

والخيار الثاني:

(defvar *fn* (compile nil '(lambda (a) (+ a 2))))
(funcall *fn* 4)
=>
6
scroll top