سؤال

لقد كنت أعمل من خلال اللثغة المشتركة العملية وكتمرين، قررت كتابة ماكرو لتحديد ما إذا كان الرقم مضاعفًا لرقم آخر:

(defmacro multp (value factor)
`(= (rem ,value ,factor) 0))

لهذا السبب :(multp 40 10)يتم تقييمه إلى صحيح بينما(multp 40 13)لا

السؤال هو هل هذا الماكرو تسريب بطريقة ما؟أيضا هل هذه اللثغة "الجيدة"؟هل هناك بالفعل وظيفة/ماكرو موجود يمكنني استخدامه؟

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

المحلول

يقدم Siebel ملخصًا شاملاً (للحالات البسيطة على أي حال) للمصادر المحتملة للتسريبات، ولا يوجد أي منها هنا.كلاهما value و factor يتم تقييمها مرة واحدة فقط وبالترتيب، و rem ليس له أي آثار جانبية.

لكن هذا ليس Lisp جيدًا، لأنه لا يوجد سبب لاستخدام الماكرو في هذه الحالة.وظيفة

(defun multp (value factor)
  (zerop (rem value factor)))

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

نصائح أخرى

الماكرو الخاص بك يبدو جيدا بالنسبة لي.لا أعرف ما هو الماكرو المتسرب، لكن الماكرو الخاص بك واضح جدًا ولا يتطلب أي gensyms.بقدر ما إذا كانت هذه Lisp "جيدة"، فإن قاعدتي الأساسية هي استخدام الماكرو فقط عندما لا تعمل الوظيفة، وفي هذه الحالة يمكن استخدام الوظيفة بدلاً من الماكرو الخاص بك.ومع ذلك، إذا كان هذا الحل مناسبًا لك، فلا يوجد سبب لعدم استخدامه.

حسنًا، من حيث المبدأ، يمكن للمستخدم القيام بذلك:

(flet ((= (&rest args) nil))
  (multp 40 10))

والتي سيتم تقييمها إلى NIL ...باستثناء أن ANSI CL يجعل من غير القانوني إعادة ربط معظم الرموز القياسية، بما في ذلك CL:=، لذا فأنت في الجانب الآمن في هذه الحالة بالذات.

بشكل عام، بالطبع، يجب أن تكون على دراية بكل من عدم الشفافية المرجعية (التقاط المعرفات من السياق الذي تم توسيع الماكرو فيه) وعدم النظافة الكلية (تسريب المعرفات إلى التعليمات البرمجية الموسعة).

لا، لا يتم تحرير أي رمز تم إدخاله في "الإغلاق المعجمي" للماكرو إلى الخارج.

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

(defmacro ana-and (&rest forms)
  (loop for form in (reverse forms)
        for completion = form then `(let ((it ,form))
                                      (when it
                                       ,completion))
        finally (return completion)))

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

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