Using Let in Scheme

26,712

Solution 1

Use let* instead of let.

The difference between let and let* is the following:

let* binds variables from left to right. Earlier bindings can be used in new binding further to the right (or down).

let on the other hand can be thought of as syntactic sugar (or macro) for simple lambda abstraction:

(let ((a exp1)
      (b exp2))
   exp)

is equivalent to

((lambda (a b)
    exp)
 exp1 exp2)

Solution 2

  • 4ac is a variable with a numeric value, so (4ac) is not meaningful.

  • LET binds all variables, but the variables can't be used in the computations for the values.

This does not work:

(let ((a 1) (b 1) (c (* a b)))
   c)

Use:

(let ((a 1) (b 1))
  (let ((c (* a b)))
    c))

Above introduces A and B with the first LET. In the second LET both A and B now can be used to compute C.

Or:

(let* ((a 1) (b 1) (c (* a b)))
   c)

Solution 3

You'll need a special let-construct (let*) here since the variables inside the let-definition refer to each other.

It's rather a problem of defining a scope than of evaluating an expression (In usual let-definitions, the order of evaluation doesn't matter since the values may not use each other)

Solution 4

When you use let, the bindings are not visible in any of the bodies. Use let* instead and see the RNRS docs for details.

Share:
26,712
unj2
Author by

unj2

.

Updated on February 23, 2020

Comments

  • unj2
    unj2 about 4 years

    I want to write a program to find the roots of the quadratic equation in Scheme. I used LET for certain bindings.

    (define roots-with-let
      (λ (a b c)
        (let ((4ac (* 4 a c))
              (2a (* 2 a))
              (discriminant (sqrt ( - (* b b) (4ac)))))
          (cons ( / ( + (- b) discriminant) 2a)
                ( / ( - (- b) discriminant) 2a)))))
    

    I defined the discriminant with 4ac since I did not want (* 4 a c). Even though I have defined (4ac (* 4 a c)), it is giving me this error:

    expand: unbound identifier in module in: 4ac.

    My question is how is let evaluated (what order)? And if i want 4ac in my let should i write another inner let? Is there a better way to do this?

  • unj2
    unj2 almost 15 years
    Could you please comment on the difference of the evaluation order between the two?
  • nullException
    nullException almost 15 years
    it's not (only) about evaluation order, it's mostly about scope. in the plain let, the scope of every variable is only the expression, not the bindings. in let*, the scope of each variable is the expression and every binding after itself.