using lambda instead of let in scheme

2019-04-07 07:25发布

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.

4条回答
做自己的国王
2楼-- · 2019-04-07 07:53
(define-syntax let-as-lambda
  (syntax-rules ()
        ((_ (x value) body)
            (let ((x value))
              body))))

(printf "~s~n" (let-as-lambda (x 1) (+ x 1)))
查看更多
男人必须洒脱
3楼-- · 2019-04-07 07:59

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)))
查看更多
Juvenile、少年°
4楼-- · 2019-04-07 08:02

Let us examine two simple cases so that we can understand how we can rewrite any function that uses let with lambda:

  1. 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.

  1. 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!

查看更多
一纸荒年 Trace。
5楼-- · 2019-04-07 08:12

These two things are same:

((lambda (p1 p2...) body) v1 v2...)

and

(let ((p1 v1) (p2 v2)...) body)
查看更多
登录 后发表回答