在为MIT/GNU Scheme(rel 9.2 )开发经典的练习代码odd
和even
函数时,我遇到了一个问题,即我的代码不会因大整数值而终止。首先,我测试了以下代码,它同时处理正值和负值:
(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
但是这个版本也不返回大整数。所以,我有这些相关的问题:
- 特征。MIT/GNU 方案中的相互递归函数是否完全优化?
- 诊断。有什么方法可以告诉Scheme编译器/解释器确实为相互尾递归优化了函数。那么,如何判断问题出在(不存在)尾递归优化或其他问题上。
- 什么是正确的相互尾递归?我的初始代码是否符合优化条件?我的第二次参加有资格吗?