سؤال
أنا أتعلم SICP الآن وأقوم بـ ex2.23 لقد قمت بإعداد الكود التالي:
(define (for-each proc items)
(if (null? items)
#t
((proc (car items))
(for-each proc (cdr items)))))
ولكن عند الجري ، تسبب خطأ: تطبيق الإجراء: الإجراء المتوقع ، المعطى: #؛ كانت الحجج: ()
أعتقد أنني أعرف السبب: أنا أسمي الوظيفة المؤثرة بشكل متكرر ، كل ما يسمى إلى EACH يريد إرجاع القيمة
ولكن عندما قمت بتعديل الكود:
(define (for-each proc items)
(cond ((null? items) #t)
(else (proc (car items)) (for-each proc (cdr items)))))
إنه يعمل بشكل جيد. لا أفهم ، لماذا؟ في كوند, ، هل كل ما يسمى لا حاجة إلى إرجاع القيمة؟
لقد استخدمت DrScheme ، واختيار اللغة SICP
أنا لست متحدثًا أصليًا للغة الإنجليزية ، لذلك إذا كان هناك STH لم يتم وصفه بوضوح ، فالرجال أخبرني
المحلول
ولكن عند التشغيل ، خطأ السبب: تطبيق الإجراء: متوقع> الإجراء ، معطى: #؛ كانت الحجج: ()
أعتقد أنني أعرف السبب: أنا أسمي الوظيفة الخاصة بـ EACH بشكل متكرر ،> كل مدعو إلى EACH أراد إرجاع القيمة
لا ، لأنه في البديل البديل لـ if
لديك المجموعة ((proc (car items)) (for-each proc (cdr items)))
. كنت تنوي تقييم المجموعتين (proc (car items))
و (for-each proc (cdr items))
بالتتابع ، ولتحقيق هذه الغاية ، كنت تعتقد أن وضعهم في زوج آخر من الأقواس سيعمل. ولكن في الواقع ، ما حددته هو أن نتيجة (proc (car items))
هو إجراء يتم تطبيقه على الوسيطة التي هي قيمة الإرجاع (for-each proc (cdr items))
. هذا ليس هو الحال ، وستحصل على خطأ. النقطة الأساسية هي أن الأقواس في LISP ليست للتجميع ، ولكن لها أهمية محددة.
المشكلة هي if
يمكن أن يكون لديك مزيج واحد فقط في هذا الموقف ، في حين أنك تريد أن يكون لديك اثنين على التوالي. من ناحية أخرى، cond
لا يعاني من هذا التقييد. يمكنك وضع سلسلة من التوليفات الفردية لفترة طويلة في الجزء الناتج عن أ cond
بند كما يرغب قلبك. هذه الحالة هي ببساطة كيف يتم تعريف اللغة للعمل.
يمكنك الاستخدام أيضًا cond
في هذه المواقف ، ولكن إذا كنت لا تزال ترغب في الاستخدام if
هناك بعض الخيارات لمحشو مجموعات متعددة في واحدة. E. G. يمكنك إنشاء إجراء Lambda الذي يكون جسده هو المجموعتين وإطلاقه على الفور:
(define (for-each proc items) (if (null? items) #t ((lambda () (proc (car items)) (for-each proc (cdr items)) )) ))
أو يمكنك استخدام begin
الذي من المفترض أن يتم استخدامه في الواقع لهذا الغرض:
(define (for-each proc items) (if (null? items) #t (begin (proc (car items)) (for-each proc (cdr items)) ) ))