(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)
但不是在标准方案中...
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)
但不是在标准方案中...