مخطط/مضرب: قم بترتيب التقييم حلقة
-
02-10-2019 - |
سؤال
الإجراء التالي صالح في كلا المخططين 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))
الذي في المضرب مضمون لإرجاع قائمة من السطر الأول ، ثم الثانية. قد تُرجع التطبيقات الأخرى الخطين بترتيب مختلف.