(define (decode bits tree)
(define (decode-1 bits current-branch)
(if (null? bits)
'()
(let ((next-branch (choose-branch (car bits) current-branch)))
(if (leaf? next-branch)
(cons (symbol-leaf next-branch)
(decode-1 (cdr bits) tree))
(decode-1 (cdr bits) next-branch)))))
(decode-1 bits tree))
如果我们对decode-1
和decode
使用相同的参数,为什么我们甚至需要decode-1
?
答案 0 :(得分:1)
decode-1
实际上是指decode
参数tree
(在(decode-1 (cdr bits) tree)
中),而不仅仅是current-branch
。所以他们不是“相同的论点”。 (在技术方面,decode-1
是closure。)
如果decode-1
没有引用tree
(或者通常是任何外部变量),那么是的,您可以直接递归decode
而不需要内部过程。< / p>
顺便说一句,“定义一个过程并调用它”这个习惯用法非常普遍,Scheme提供了一个"named let
" syntax来更好地编写它:
(define (decode bits tree)
(let decode-1 ((bits bits) (current-branch tree))
(if (null? bits)
'()
(let ((next-branch (choose-branch (car bits) current-branch)))
(if (leaf? next-branch)
(cons (symbol-leaf next-branch) (decode-1 (cdr bits) tree))
(decode-1 (cdr bits) next-branch))))))
答案 1 :(得分:0)
制作此类内部过程的一个优点是您可以简单地修改其实现而无需更改参数计数。例如,添加一个额外的参数作为过程的累加器,以便它可以是尾递归的。 decode-1
不正确的尾递归,因此如果位和 tree 太大,则实现可能会导致堆栈溢出。
以下是转换decode
尾递归调用的示例:
(define (decode bits tree) (define (decode-1 bits current-branch acc) (if (null? bits) (reverse acc) (let ((next-branch (choose-branch (car bits) current-branch))) (if (leaf? next-branch) (decode-1 (cdr bits) tree (cons (symbol-leaf next-branch) acc)) (decode-1 (cdr bits) next-branch acc))))) (decode-1 bits tree '()))
<强>已更新强>
上面的代码也可以用named-let编写。因此,当您想用内部定义编写它时,情况将是以下情况。
letrec
完成,但嵌套级别会稍微深一些。因此,在您的情况下,choose-branch
可以在decode
过程中编写。define-syntax
的内部宏定义,那么您只能使用内部定义编写它。 R7RS的let(rec)-syntax
创建了一个范围,但内部define-syntax
和define
应该被视为在同一范围内。 我不确定R7RS是否指定了内部宏的扩展方式(例如,首先扩展所有宏,如R6RS)。