【问题标题】:Usage of nested let or let* in scheme在方案中使用嵌套的 let 或 let*
【发布时间】:2015-11-17 09:29:18
【问题描述】:

我正在编写一个以间隔作为参数并返回百分比错误的函数,但我坚持使用 let 或 let*。代码如下:

嵌套让版本:

(define (percent interval)
  (let (start-point (car interval))
    (let (end-point (cdr interval))
      (let (center (/ (+ start-point end-point) 2)))))
  (/ (- end-point center) center))

错误是:let: bad syntax (not an identifier and expression for a binding) in: start-point

让*版本:

(define (percent interval)
  (let* ((start-point (car interval))
     (end-point (cdr interval))
     (center (/ (+ start-point end-point) 2))))
  (/ (- end-point center) center))

现在的错误是:

let*: bad syntax (missing body) in: (let* ((start-point (car interval)) (end-point (cdr interval)) (center (/ (+ start-point end-point) 2))))

我参考了一些文档,但也无法找出错误所在。 (ps:我用的是 DrRacket 6.2)

【问题讨论】:

  • 你提到你正在使用 DrRacket。您使用的是 Racket 语言、Scheme 语言之一(R5RS 或 R6RS)还是教学语言之一?
  • 我正在使用 Scheme 但 Racket 不是 Scheme 的严格超集吗?
  • 不完全是,加上各种方言都有点不同。 精确地指定你正在使用的 Scheme 的变体通常很有用——它们都不完全相同。
  • 哦,抱歉,我刚刚注意到我实际上在使用 Racket,它是由 #lang racket 指定的

标签: scheme racket


【解决方案1】:

最后的表达式,除法本身,需要进入let*。这是因为let 表单引入了仅在词法范围内对其主体的绑定。此外,let 形成 require 一个主体,这就是您收到该错误的原因(在您的示例中,它们根本没有主体,因为最终表达式在它们之外)。

要解决这个问题,只需在 let* 表单中移动最后一个表达式:

(define (percent interval)
  (let* ((start-point (car interval))
         (end-point (cdr interval))
         (center (/ (+ start-point end-point) 2)))
    (/ (- end-point center) center)))

您使用嵌套 let 的版本在另一种方面略有错误:您缺少每个绑定对的括号级别,这导致了第一个错误。也就是说,而不是这个:

(let (start-point (car interval))
  ...)

...你需要这个:

(let ((start-point (car interval)))
  ...)

注意多余的括号。也就是说,let* 版本要好得多!它只是用于嵌套 let 表单的宏,它会自动进行嵌套,因此您不必这样做。

还有一件事:如果您正在编写可移植的 Scheme,则所有括号都必须是括号。但是,如果您正在编写 Racket,则可以将方括号 可互换 与圆括号一起使用。因此,惯用的 Racket 在某些地方使用方括号作为一种风格选择,以使代码更具可读性。

其中一种情况是在let 绑定对中。因此,惯用的 Racket 代码如下所示:

(define (percent interval)
  (let* ([start-point (car interval)]
         [end-point (cdr interval)]
         [center (/ (+ start-point end-point) 2)])
    (/ (- end-point center) center)))

这只是有助于更清楚地表明每一对都在创建一个绑定,而不是调用一个函数。

【讨论】:

  • 非常感谢。?现在我成功了。在 Racket 中嵌套的 let 肯定比 let* 复杂得多,但是在 MIT Scheme 中的 let 结构中,额外的括号并不是必不可少的。
  • 方括号与R6RS Scheme中的括号相同,因此惯用的球拍代码兼容。
猜你喜欢
  • 1970-01-01
  • 2011-12-23
  • 2013-05-07
  • 1970-01-01
  • 2023-03-15
  • 2019-02-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多