باستخدام Lambda بدلاً من التخطيط للدخول
سؤال
في SICP 1.2.1 هناك وظيفة تصنع رقمًا عقلانيًا ، على النحو التالي:
(define (make-rat n d)
(let ((g (gcd n d)))
(cons (/ n g) (/ d g))))
أنا مجرد فضول كيف يمكنك تنفيذ نفس الشيء باستخدام Lambda بدلاً من السماح ، دون الاتصال GCD مرتين. لم أستطع معرفة ذلك بنفسي.
المحلول
انظر الى SICP القسم 1.3.2,
(let ((<var1> <exp1>)
(<var2> <exp2>)
...
(<varn> <expn>))
<body>)
يعادل
((lambda (<var1> ...<varn>)
<body>)
<exp1>
...
<expn>)
لذلك الإجراء الخاص بك ،
(define (make-rat n d)
(let ((g (gcd n d)))
(cons (/ n g) (/ d g))))
يجب أن تكون مكافئة ل
(define (make-rat n d)
((lambda (g)
(cons (/ n g) (/ d g)))
(gcd n d)))
نصائح أخرى
هذين الأمرين هو نفسه:
((lambda (p1 p2...) body) v1 v2...)
و
(let ((p1 v1) (p2 v2)...) body)
(define-syntax let-as-lambda
(syntax-rules ()
((_ (x value) body)
(let ((x value))
body))))
(printf "~s~n" (let-as-lambda (x 1) (+ x 1)))
دعنا نفحص حالتين بسيطتين حتى نتمكن من فهم كيف يمكننا إعادة كتابة أي وظيفة تستخدم مع Lambda:
في حالتنا الأولى ، لدينا واحدة. هذه الوظيفة بسيطة للغاية ، فهي تُرجع إدخالًا معينًا بإضافة 10 إلى:
(define (test x) (let ((b 10)) (+ x b)))
الآن دعونا نحول هذا إلى تعبير باستخدام Lambda:
(define (test-lambda x)
((lambda (b)
(+ x b))
10))
كما ترون ، يقوم اختبار Lambda بإرجاع تقييم Lambda الذي يتم تقييمه مع القيمة 10. اختبار هذا يمكننا القول:
(test-lambda 10)
التي ستعود 20.
- الآن لأكثر من واحد ، نحن ننشأ معبرات Lambda داخل التعبيرات Lambda.
قضية LET لدينا تصريحان LET:
(define (lets x)
(let ((a 10)
(b 20))
(+ x a b)))
يمكننا كتابة هذا مع Lambda مثل ذلك:
(define (lets-lambda x)
((lambda (a)
((lambda (b)
(+ x a b))
20))
10))
والآن نقوم بتقييم كل من تعبيرات Lambda التي تمنحهم قيمة ، ويهتم تعبير Lambda الأعمق بما نريد حسابه باستخدام أسماء متغيرة تم تعيين كل تعبير Lambda.
آمل أن يكون هذا واضحًا وقد يساعد الآخرين على الرؤية بشكل أكثر وضوحًا!