Scheme 为什么是内部程序?
如果我们对Scheme 为什么是内部程序?,scheme,procedure,Scheme,Procedure,如果我们对decode和decode-1使用相同的参数,为什么我们甚至需要decode-1?decode-1实际上指的是decode参数树(在(解码-1(cdr位)树中)),而不仅仅是指当前分支。所以他们不是“相同的论点”。(在技术术语中,decode-1是一种编码。) 如果decode-1没有引用树(或者通常没有引用任何外部变量),那么是的,您可以直接递归到decode,而不需要内部过程 顺便说一句,“定义一个过程并调用它”的习惯用法非常常见,Scheme提供了一个更好地编写它的方法: (de
decode
和decode-1
使用相同的参数,为什么我们甚至需要decode-1
?decode-1
实际上指的是decode
参数树(在(解码-1(cdr位)树中)
),而不仅仅是指当前分支
。所以他们不是“相同的论点”。(在技术术语中,decode-1
是一种编码。)
如果decode-1
没有引用树(或者通常没有引用任何外部变量),那么是的,您可以直接递归到decode
,而不需要内部过程
顺便说一句,“定义一个过程并调用它”的习惯用法非常常见,Scheme提供了一个更好地编写它的方法:
(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
尾部递归调用的示例:
(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位当前分支acc)
(如果为空位)
(倒车加速)
(let((下一个分支(选择分支(汽车位)当前分支)))
(如果(叶?下一分支)
(解码-1(cdr位)树(cons(符号叶下一分支)acc))
(解码-1(cdr位)下一分支acc(()())))
(解码-1位树“()))
已更新
上面的代码也可以使用命名let编写。因此,当您想用内部定义编写它时,情况如下
如果内部程序有交叉引用,那么它可以是您可以选择的选项之一。这也可以通过letrec
实现,但嵌套级别会稍微深一些。因此,在您的情况下,choose branch
可以写入decode
过程中
如果toplevel过程包含带有定义语法的内部宏定义
,则只能使用内部定义编写。R7RS的let(rec)-语法
创建了一个作用域,但内部定义语法
和定义
应被视为处于同一作用域中李>
我不确定R7RS是否指定内部宏的扩展方式(例如,首先扩展所有宏,如R6RS)。否,您不能“简单地消除内部定义”。正如我在回答中提到的,内部过程是一个闭包。事实上,即使您的尾部递归定义仍然是一个闭包,因此您仍然无法在不添加额外的树
参数的情况下将其提升到顶级过程。对不起,我没有注意到树
参数。前两句应该是。你能解释一下尾部递归版本是如何工作的吗?我看不懂代码。。。如果位为空,为什么要反转acc?我现在明白为什么要反转acc。。。是否可以这样做,这样您就不必将其反转?您也可以使用append
而不是cons
来避免反转
,但这需要O(n^2)的成本,因为追加了O(n)。
(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 '()))