我正在努力解决let,letrec,let * ...之间的区别因为scheme不是我的主要编程语言,我的内存不存在很长时间..我有这个功能..现在我很困惑这里的letrec ..这又是递归 . 我可以理解......但是在这段代码中无法 Build 足够的连接..(可能仍然对递归感到困惑)有人可以解释为什么这里需要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进行尾递归吗?
这个函数返回x,y的列表,其边界为start,end,所以它检查索引i是否在边界内,如果是,则执行第6行
-
[Q3]那么,line6是什么?我无法获得line6
3 回答
[Q1] 尾部递归吗?
Answer 是的,它会进行尾递归 .
[Q2] 那么,应该总是使用letrec进行尾递归吗?
Answer 有两种解释问题的方法 .
letrec
进行尾递归吗?我不认为你是这么想的 . 但......答案是不 . 顶级lambda函数也可用于尾递归 .
letrec
应该总是使用尾递归吗?答案是:任何递归函数最好是尾递归 . 如果可以的话,你应该让它递归 .
[Q3] 那么line6是什么?
第6行的代码执行递归调用 .
假设
start
是0
,end
是5
,res
是1
. 在第一次调用func:rec_func
时,x
是空列表()
,i
是5
,y
是空列表()
.当在第6行调用第一个递归函数时,参数为
(cons i x)
,(- i res)
和(cons (func i) y)
,其值为:(5)
,4
和((func 5)
.在下一次迭代中,参数是
(4 5)
,3
和((func 4) (func 5))
.它一直持续到
i
变得小于start
. 然后递归停止,结果为((0 1 2 3 4 5) ((func 0) (func 1) (func 2) (func 3) (func 4) (func 5)))
第7行的代码在满足递归的终止标准时执行,即
(>= i start)
为false时 .与letrec,let和let *的不同之处在于它们执行程序可用的声明 .
回顾一下:
用letrec声明的变量的范围是在letrec体内的ALL . 编译器做了一些魔术,所以在声明结束后替换引用 .
使用let *声明的变量的范围是变量声明后let *范围内的所有表达式 .
用let声明的变量的范围只是let的主体,而不是声明部分 .
如果我没记错的话,这个构造需要
letrec
而不是let
或let*
,因为func:rec_func
的主体指的是它自己 . 如果你在这里使用let
或let*
,嵌套lambda中的符号func:rec_func
将被绑定到顶级表单外可见的任何定义,或者如果没有这样的定义则不定义 - 也不是你想要的 .