在Scheme中的相互递归中实现尾部调用优化

问题描述

MIT / GNU方案(相对于 9.2 )中为oddeven函数开发经典的练习代码时,我遇到了我的代码不会因大整数值而终止的问题。 首先,我测试了以下代码,该代码同时处理正值和负值:

(define error-message-number "Error. x must be a number")

(define odd?
  (lambda (x)
    (cond 
      ((not (integer? x)) error-message-number)
      ((= x 0) #f)
      ((< x 0) (even? (+ x 1))) ;for negatives
      (else (even? (- x 1)))))) ;if number n is odd then n - 1 is even 

(define even?
  (lambda (x)
    (cond 
      ((not (integer? x)) error-message-number)
      ((= x 0) #t)
      ((< x 0) (odd? (+ x 1))) ;for negatives
      (else (odd? (- x 1)))))) ;if number n is even then n - 1 is odd

电话(assert (equal? #f (even? 100000000001)))(assert (equal? #t (odd? -100000000001)))不会在我的计算机上终止,例如(assert (equal? #f (even? 1001)))(assert (equal? #t (odd? -1001)))可以。 我的第一个想法是代码并未针对正确的尾部递归进行优化,而我没有一个,而是在每个函数中有两个尾部调用。 因此,我决定简化任务,只取正整数,就像这样:

(define error-message-positive "Error. x must be a nonnegative number")

(define odd-positive?
  (lambda (x)
    (cond 
      ((not (integer? x)) error-message-number)
      ((= x 0) #f)
      ((< x 0) error-message-positive) ;for negatives
      (else (even? (- x 1)))))) ;if number n is odd then n - 1 is even 

(define even-positive?
  (lambda (x)
    (cond 
      ((not (integer? x)) error-message-number)
      ((= x 0) #t)
      ((< x 0) error-message-positive) ;for negatives
      (else (odd? (- x 1)))))) ;if number n is even then n - 1 is odd

但是此版本对于大整数都不返回。 因此,我有以下相关的问题

  1. 功能。 MIT / GNU Scheme中的相互递归函数是否已完全优化?
  2. 诊断程序。有什么办法可以告诉方案确实由Scheme编译器/解释器针对相互尾递归进行了优化。因此,如何判断问题出在(没有)尾递归优化上,还是其他事情上。
  3. 什么是正确的相互尾部递归?我的初始代码是否有资格进行优化?我的第二张参赛资格吗?

解决方法

  1. 什么是正确的相互尾巴递归?

就像您的代码一样,它们都是两个版本。

  1. 诊断。

Empirical orders of growth FTW!

您的诊断可能不正确。特别是在我的机器上的Racket中,代码完成的预期时间为 40 分钟。而且它似乎确实在整体内存中运行。

是的,即使在恒定的空间中运行,它仍然需要时间来保持参数大小的线性关系。我怎么知道?我只是用时钟墙时间来测量它,的确确实是线性的,即 n 1 幂定律。约。 (即,无论是1.02还是0.97,它仍然指示线性增长率。这很重要。)

另请参阅:

  1. 功能。 MIT / GNU方案中的相互递归函数是否已完全优化?

必须这样,因为尾部调用优化在语言规范中。而且TCO不仅是尾部递归,据我了解,即使下一个调用的决定是动态的(更不用说是静态的,在您的情况下在代码中也很明显),当一个尾部调用时,它仍然必须在恒定的堆栈空间中运行最终导致再次进入相同的功能。尾部调用是尾部调用,无论调用什么,都必须对其进行优化。我目前没有官方报价。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...