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

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

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

引用行

(let ((next (f guess)))

我假设添加了额外的括号,并将其更改为

(let (next (f guess))

运行 再次尝试但拒绝工作

#+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:

有什么问题?

这只是语法问题,您应该查看 let 的文档。它需要一个 list 的绑定和一个主体,其中每个出价都是一个包含两个元素的列表,一个变量名和一个表达式 - 所以这是正确的方法(添加额外的换行符进行解释, 但你永远不应该像这样缩进):

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

您的尝试失败:

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

... 因为它缺少在正文部分之前分隔绑定列表的外部 ()。现在应该很明显,我们可以将多个绑定作为 let 的一部分,这就是绑定列表的外部 () 是强制性的原因。

方案

I assumed that extra parenthesis are added

在方案一中不能这样假设。通常括号不是可选的,而是表达式语法的必要部分。

方案(R5RS、R6RS、R7RS)中let的语法是:

(let <bindings> <body>) 

Syntax: <Bindings> should have the form

((<variable1> <init1>) ...)

因此在您的示例中,next 是变量,(f guess) 是初始形式。

您试图省略一级括号导致语法错误。以下形式不是有效的方案。

(let (next          ;  a symbol is not allowed, only (var init) lists
      (f guess))    ;  variable 'f' and init form 'guess'
  ...
  )

语法与其他一些 Lisp 语言略有不同。

Emacs Lisp

参见 Emacs Lisp 示例:3.6.1 The Parts of a let Expression

因此在 Emacs Lisp 中可以只写一个变量,这样它就会绑定到 nil:

(let ((var1 init1)
      var2
      (var3 init3)
      var4
      ...)
  ...)

Common Lisp

Common Lisp 也允许省略 init 形式。语法:

let ({var | (var [init-form])}*) declaration* form*

因此在 Common Lisp 中我们也可以有

CL-USER > (let ((a 10)     ; a bound to 10
                b          ; b bound to NIL 
                (c))       ; c bound to NIL
            (list a b c))
(10 NIL NIL)

但不是在标准方案中...