سؤال

الإجراء التالي صالح في كلا المخططين R6Rs والمضرب:

;; create a list of all the numbers from 1 to n
(define (make-nums n)
  (do [(x n (- x 1)) (lst (list) (cons x lst))]
    ((= x 0)
     lst)))

لقد اختبرته لكل من R6Rs و Dracket وهو يعمل بشكل صحيح ، لكنني أعرف ذلك بالتأكيد بالتأكيد على Drracket.

سؤالي هو إذا كان كذلك مضمون أن تعبيرات الخطوة ((- x 1) و (cons x lst) في هذه الحالة) سيتم تقييمها بالترتيب. إذا لم يكن مضمونًا ، فإن الإجراء الخاص بي ليس مستقرًا للغاية.

لم أر أي شيء يحدد هذا في معايير أي من اللغة ، لكنني أسأل هنا لأنه عندما اختبرت أنه تم إبعاده بالترتيب.

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

المحلول

بشكل عام غير مضمون لتقييمه بالترتيب ، لكن النتيجة ستظل هي نفسها. هذا لأنه لا توجد آثار جانبية هنا-لا تتغير الحلقة x أو lst, ، إنه يعيد إعادة صياغته إلى قيم جديدة ، وبالتالي فإن الترتيب الذي يتم فيه تقييم التعبيرات ذات الخطتين غير ذي صلة.

لرؤية هذا ، ابدأ بإصدار نظافة من الكود الخاص بك:

(define (make-nums n)
  (do ([x n (- x 1)] [lst null (cons x lst)])
      [(zero? x) lst]))

ترجمة إلى اسم-let:

(define (make-nums n)
  (let loop ([x n] [lst null])
    (if (zero? x)
      lst
      (loop (- x 1) (cons x lst)))))

وترجمة ذلك إلى وظيفة المساعد (وهو ما تم تسميته-let حقا هو):

(define (make-nums n)
  (define (loop x lst)
    (if (zero? x)
      lst
      (loop (- x 1) (cons x lst))))
  (loop n null))

يجب أن يكون من الواضح الآن أن ترتيب تقييم التعبيرين في العودية loop المكالمة لا تجعلها تفعل أي شيء مختلف.

أخيرًا ، لاحظ أنه في تقييم المضرب هو مضمون أن يكون اليسار إلى اليمين. هذا مهم عندما يكون هناك آثار جانبية-تفضل المضرب سلوكًا يمكن التنبؤ به ، في حين يعترض الآخرون على ذلك ، مدعيا أن هذا يقود الناس إلى رمز يعتمد ضمنيًا على هذا. مثال صغير شائع يوضح الفرق هو:

(list (read-line) (read-line))

الذي في المضرب مضمون لإرجاع قائمة من السطر الأول ، ثم الثانية. قد تُرجع التطبيقات الأخرى الخطين بترتيب مختلف.

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