Search code examples
syntaxschemelispletsicp

(let (next (f guess)) vs (let ((next (f guess)))


The fix-point practice in sicp

#+BEGIN_SRC scheme
(define tolerance 0.00001)

(define (fixed-point f first-guess)
  (define (close-enough? v1 v2)
    (< (abs (- v1 v2)) tolerance))
  (define (try guess)
    (let ((next (f guess)))
      (if (close-enough? guess next)
          next
          (try next))))
  (try first-guess))
(fixed-point cos 1.0)
#+END_SRC

#+RESULTS:
: 0.7390822985224024

Reference the line

(let ((next (f guess)))

I assumed that extra parenthesis are added, and changed it to

(let (next (f guess))

run it again but refuse to work

#+BEGIN_SRC scheme
(define tolerance 0.00001)

(define (fixed-point f first-guess)
  (define (close-enough? v1 v2)
    (< (abs (- v1 v2)) tolerance))
  (define (try guess)
    (let (next (f guess))
      (if (close-enough? guess next)
          next
          (try next))))
  (try first-guess))
(fixed-point cos 1.0)
#+END_SRC

#+RESULTS:

What's the problem?


Solution

  • It's just a matter of syntax, you should check the documentation for let. It expects a list of bindings and a body, where each biding is a list with two elements, a variable name and an expression - so this is the correct way (added extra line breaks for explanation, but you should never indent like this):

    (let ( ; start list of bindings
          ( ; start binding
           next ; binding name
           (f guess) ; binding value
          ) ; end binding
         ) ; end list of bindings
      <body>)
    

    Your attempt failed:

    (let (next (f guess))
      ...)
    

    ... Because it's missing the outer () that delimit the list of bindings, before the body part. It should be obvious by now that we can have multiple bindings as part of a let, that's why the outer () for the list of bindings are mandatory.