【问题标题】:Scheme lambda and let errors计划 lambda 并让错误
【发布时间】:2018-04-27 12:06:51
【问题描述】:

scheme的初学者..尝试以下代码来测试lambda的等价性并让

(lambda (x y)
  (+ x y)
  10
  (* x 2))

(let ((k 10)
      (y (* 2 k)))
  (+ k y))

输出是

#<procedure>
. . k: undefined;
 cannot reference undefined identifier
> 

任何帮助将不胜感激

【问题讨论】:

  • 第一个表达式看起来很糟糕。它添加了xy 并忘记了结果。表达式实际做的唯一事情是将x 加倍,因为函数只返回最后一个表达式的值。
  • let-binding 不等同于 lambda,它等同于应用于参数的 lambda。 (let ((x e)) body) ((lambda (x) body) e).

标签: lambda scheme racket


【解决方案1】:

let 中的绑定不能在let 表单的正文之前使用。因此你需要定义k:

(define k 99)

(let ((k 10)
      (y (* 2 k))) ; the k here is not the one in the same `let`
  (+ k y))
; ==> 208

let 只是被调用匿名过程的语法糖。等于这个:

((lambda (k y)
   (+ k y))
 10
 (* 2 k))

使用这种语法可能更明显k 不能是分配给10 的那个?还有另一种语法称为let*,它允许您使用以前的绑定:

(let* ((k 10)
       (y (* 2 k))) ; the k here is not the one in the same `let`
  (+ k y))
; ==> 30

相当于嵌套匿名过程调用:

((lambda (k)
   ((lambda (y)
      (+ k y))
    (* 2 k)))
 10)

这里很容易看出(* 2 k)中的k是绑定到10的那个。

【讨论】:

    【解决方案2】:

    FWIW,相当于lambda 构造到

    (let ((k 10))
      (let ((y (* 2 k)))
        (+ k y)))
    

    ((lambda (k)
       ((lambda (y)
          (+ k y))
        (* 2 k)))
     10)
    

    【讨论】:

      【解决方案3】:

      方案的let有两个限制。

      1. let 定义的变量对后续定义的主体不可见。
      2. let 定义的变量对定义本身不可见。

      第一个限制适用于您的示例。

      (let ((k 10)
            (y (* 2 k)))
        (+ k y))
      

      在此示例中,ky 在同一个 let 中定义。 y 的正文确实知道k。为了使ky 的主体可见,您必须使用两个let 表达式。

      (let ((k 10))
        (let ((y (* 2 k)))
          (+ k y)))
      

      为了避免这种嵌套,Scheme 提供了let* 替代方案。

      (let* ((k 10)
             (y (* 2 k)))
        (+ k y))
      

      如果您阅读了let* 的规范,您应该考虑同时阅读letrec 的规范,这样就消除了第二个限制。

      【讨论】:

        猜你喜欢
        • 2015-05-19
        • 2017-01-28
        • 1970-01-01
        • 2021-07-29
        • 2021-08-15
        • 2023-03-14
        • 2010-12-22
        • 2013-02-03
        • 2011-09-26
        相关资源
        最近更新 更多