سؤال

أحاول معرفة كيف يمكنني القيام ب "عودة مبكرة" في إجراء مخطط بدون باستخدام المستوى الأعلى if أو cond مثل بناء.

(define (win b)
 (let* ((test (first (first b)))
        (result (every (lambda (i) (= (list-ref (list-ref b i) i) test))
                       (enumerate (length b)))))
  (when (and (not (= test 0)) result) test))
 0)

على سبيل المثال، في الكود أعلاه، أريد win لكي ترجع test إذا كان when يتم تلبية الشرط، وإلا فإن العودة 0. ومع ذلك، ما يحدث هو أن الإجراء سوف دائما العودة 0، بغض النظر عن نتيجة when شرط.

السبب في أنني تنظم الرمز الخاص بي بهذه الطريقة لأنه في هذا الإجراء أحتاج إلى القيام العديد من الشيكات المعقدة (كتل متعددة مماثلة ل let* في المثال) ووضع كل شيء في كبيرة cond سيكون غير عملي للغاية.

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

المحلول

فيما يلي كيفية استخدام Call / CC للبناء return نفسك.

(define (example x)
  (call/cc (lambda (return)
    (when (< x 0) (return #f))
    ; more code, including possible more calls to return
    0)))

تحدد بعض المخططات ماكرو يسمى السماح / CC الذي يتيح لك إسقاط بعض ضجيج Lambda:

(define (example x)
  (let/cc return
    (when (< x 0) (return #f))
    0))

بالطبع إذا لم يكن المخطط الخاص بك، فلن يتم كتابة / CC تافهة.


يعمل هذا لأن Call / CC يوفر النقطة التي تم استدعاؤها كمستمر. يمر هذا الاستمرار في وسيطة وظائفها. عندما تستدعي الوظيفة هذه الاستمرار، يتخلى المخطط أيا كان مكدس المكالمات الذي تم بناؤه حتى الآن ويستمر من نهاية مكالمة المكالمة / CC. بالطبع إذا لم تستدعي الوظيفة أبدا استمرار استمرارها، فإنها تعود عادة بشكل طبيعي.

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


لا أعرف ما يبدو وكأنه من التعليمات البرمجية الكاملة، ولكن قد يكون من الأفضل أن تذهب مع cond والعوم على الشيكات المعقدة في وظائف منفصلة. حاجة return و let* عادة ما يكون أحد أعراض الكود الحتمي بشكل مفرط. ومع ذلك، يجب أن تحصل طريقة المكالمة / CC على التعليمات البرمجية الخاصة بك الآن.

نصائح أخرى

طريقة واحدة ستكون في استخدام العودية بدلا من الحلقات، ثم يتم الآن الخروج المبكر من خلال عدم تكرار المزيد.

يمكنك استخدام دعم "الاتصال مع استمرار" محاكاة العودة. هناك مثال على ويكيبيديا. وبعد وتسمى الوظيفة دعوة مع استمرار الحالي, ، على الرغم من أن هناك في كثير من الأحيان اسم مستعار يسمى اتصل / CC. وهو بالضبط نفس الشيء. هناك أيضا مثال أنظف قليلا هنا

ملاحظة: هذه هي تقنية برمجة مخطط متقدمة، ويمكن أن تكون ثني العقل قليلا في البداية ... !!!!

في هذه الحالة، لا تريد متى، فأنت تريد أن تكون على مستوى أعلى، وإن لم يكن المستوى الأعلى.

(define (win b)
  (let* ((test (first (first b)))
         (result (every (lambda (i) (= (list-ref (list-ref b i) i) test))
                        (enumerate (length b)))))
    (if (and (not (= test 0)) result) 
        test
        0)))

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

(define foo 
  (lambda (b)
     (begin
       (let ...)
       0)))

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

غريم

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