letrec混乱,Scheme

时间:2014-05-25 01:54:05

标签: scheme letrec

我正在努力让let,letrec,让*之间的区别...... 由于方案不是我的主要编程语言,我的记忆不存在很长时间.. 我有这个功能..现在我对letrec非常困惑..这是再次递归。我能理解......但是在这段代码中无法建立连接..(可能仍然会对递归感到困惑) 谁能解释为什么这里需要letrec

(define myFunc
  (lambda (start end res func)
    (letrec ((func:rec_func
              (lambda (x i y)
                (if (>= i start)
                    (func:rec_func (cons i x) (- i res) (cons (func i) y))  ;; line6
                    (cons x (cons y '()))))))                               ;; line7
      (func:rec_func '() end '()))))

(编辑)的 我理解它的尾部递归

- > [Q1]它是否尾递归?

- > [Q2]那么,应该总是使用letrec进行尾递归吗?

此函数返回带有start,end边界的x,y列表 所以它检查索引i是否在边界内,如果是,则执行第6行

- > [Q3]那么,line6是什么?我无法获得第6行

3 个答案:

答案 0 :(得分:4)

与letrec,let和let *的区别在于他们执行程序可用的声明。

(letrec ((X (you could use X here))
         (Y (you could use X here too))
         )
     (X also is available here)
)


(let   ((X (nope, X isn't declared yet))
         (Y (in fact, no declaration body will see X))
         )
     (But X is available here)
)


(let* ((X (X isn't available here))
         (Y (but you could use it here))
         )
     (X also is available here)
)

回顾一下:

  1. 用letrec声明的变量的范围是在letrec体内的ALL。编译器做了一些魔术,因此在声明结束后替换引用。
  2. 使用let *声明的变量的范围是声明变量后let *范围内的所有表达式。
  3. 用let声明的变量的范围只是let的主体,而不是声明部分。

答案 1 :(得分:1)

如果我没记错的话,这个结构需要letrec而不是letlet*,因为func:rec_func的正文指的是它自己。如果您在此处使用letlet*,嵌套lambda中的符号func:rec_func将绑定到顶级表单 outside 之外的任何定义,或者未定义如果没有这样的定义 - 也不是你想要的。

答案 2 :(得分:0)

[Q1] 尾递归吗?

回答是的,它会进行尾递归。

[Q2] 那么,应该总是使用letrec进行尾递归吗?

回答有两种解释问题的方法。

  1. 我们是否应始终使用letrec进行尾递归?我不认为你是这么想的。但是......

    答案是否定的。顶级lambda函数也可用于尾递归。

  2. letrec是否应始终使用尾递归?

    答案是:任何递归函数最好是尾递归。如果可以的话,你应该让它递归。

  3. [Q3] 那么line6是什么?

    第6行的代码执行递归调用。

    假设start0end5res1。在第一次调用func:rec_func时,x为空列表()i5y为空列表{{ 1}}。

    当在第6行调用第一个递归函数时,参数为()(cons i x)(- i res),其评估为:(cons (func i) y),{{1} }和(5)

    在下一次迭代中,参数为4((func 5)(4 5)

    一直持续到3小于((func 4) (func 5))。然后递归停止,结果为i

    第7行的代码在满足递归的终止条件时执行,即start为假。