我正在努力让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行
答案 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 :(得分:1)
如果我没记错的话,这个结构需要letrec
而不是let
或let*
,因为func:rec_func
的正文指的是它自己。如果您在此处使用let
或let*
,嵌套lambda中的符号func:rec_func
将绑定到顶级表单 outside 之外的任何定义,或者未定义如果没有这样的定义 - 也不是你想要的。
答案 2 :(得分:0)
[Q1] 尾递归吗?
回答是的,它会进行尾递归。
[Q2] 那么,应该总是使用letrec进行尾递归吗?
回答有两种解释问题的方法。
我们是否应始终使用letrec
进行尾递归?我不认为你是这么想的。但是......
答案是否定的。顶级lambda函数也可用于尾递归。
letrec
是否应始终使用尾递归?
答案是:任何递归函数最好是尾递归。如果可以的话,你应该让它递归。
[Q3] 那么line6是什么?
第6行的代码执行递归调用。
假设start
为0
,end
为5
,res
为1
。在第一次调用func:rec_func
时,x
为空列表()
,i
为5
,y
为空列表{{ 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
为假。