In SICP 1.2.1 there is a function that makes a rational number, as follow:
(define (make-rat n d)
(let ((g (gcd n d)))
(cons (/ n g) (/ d g))))
I'm just curious how you can implement the same thing using lambda instead of let, without calling GCD twice. I couldn't figure it out myself.
Looking at SICP section 1.3.2,
(let ((<var1> <exp1>)
(<var2> <exp2>)
...
(<varn> <expn>))
<body>)
is equivalent to
((lambda (<var1> ...<varn>)
<body>)
<exp1>
...
<expn>)
So your procedure,
(define (make-rat n d)
(let ((g (gcd n d)))
(cons (/ n g) (/ d g))))
should be equivalent to
(define (make-rat n d)
((lambda (g)
(cons (/ n g) (/ d g)))
(gcd n d)))
These two things are same:
((lambda (p1 p2...) body) v1 v2...)
and
(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)))
Let us examine two simple cases so that we can understand how we can rewrite any function that uses let with lambda:
In our first case we have one let. This function is very simple, it returns a given input by adding 10 to it:
(define (test x)
(let ((b 10))
(+ x b)))
Now let us turn this into an expression using lambda:
(define (test-lambda x)
((lambda (b)
(+ x b))
10))
As you can see, test-lambda returns a lambda evaluation that is evaluated with the value 10. Testing this we can say:
(test-lambda 10)
which will return 20.
- Now for more than one let, we nest lambda-expressions within lambda-expressions.
Our let case we have two let statements:
(define (lets x)
(let ((a 10)
(b 20))
(+ x a b)))
We can write this with lambda like so:
(define (lets-lambda x)
((lambda (a)
((lambda (b)
(+ x a b))
20))
10))
So now we are evaluating each of the lambda expressions giving them a value, and the innermost lambda expression takes care of what we want to compute using the variable names that each lambda expression has been assigned.
Hope this was clear and might help others see more clearly!