【问题标题】:Using Let in Scheme在方案中使用 Let
【发布时间】:2009-06-03 17:32:45
【问题描述】:

我想写一个程序来在Scheme中找到二次方程的根。我将 LET 用于某些绑定。

(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)))))

我用4ac 定义了判别式,因为我不想要(* 4 a c)。即使我定义了(4ac (* 4 a c)),它还是给了我这个错误:

展开:模块中的未绑定标识符:4ac

我的问题是如何让评估(什么顺序)?如果我想要4ac 在我的let 中,我应该写另一个内部let 吗?有没有更好的方法来做到这一点?

【问题讨论】:

  • 这是一个来自 SICP Lecture/Book 的例子!

标签: lisp scheme


【解决方案1】:

使用let* 代替let

letlet* 的区别如下:

let* 从左到右绑定变量。较早的绑定可用于更靠右(或向下)的新绑定。

另一方面,let 可以被认为是简单 lambda 抽象的语法糖(或宏):

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

等价于

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

【讨论】:

  • 能否请您评论一下两者评估顺序的差异?
  • 这不是(仅)关于评估顺序,它主要是关于范围。在普通的 let 中,每个变量的范围只是表达式,而不是绑定。在 let* 中,每个变量的作用域是表达式及其后的每个绑定。
【解决方案2】:
  • 4ac是带数值的变量,所以(4ac)没有意义。

  • LET 绑定所有变量,但变量不能用于计算值。

这不起作用:

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

用途:

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

上面介绍了带有第一个 LET 的 A 和 B。在第二个 LET 中,A 和 B 现在都可以用来计算 C。

或者:

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

【讨论】:

    【解决方案3】:

    这里需要special let-construct (let*),因为 let 定义中的变量相互引用。

    这是一个定义范围而不是评估表达式的问题(在通常的let-definitions 中,评估顺序无关紧要,因为值可能不会相互使用)

    【讨论】:

      【解决方案4】:

      当您使用 let 时,绑定在任何主体中都不可见。请改用 let* 并查看 RNRS 文档了解详细信息。

      【讨论】:

        猜你喜欢
        • 2015-11-17
        • 2013-05-07
        • 1970-01-01
        • 2011-12-23
        • 2023-03-26
        • 2020-01-19
        • 1970-01-01
        • 1970-01-01
        • 2012-06-05
        相关资源
        最近更新 更多