While developing a classical exercise piece of code for odd
and even
functions in MIT/GNU Scheme (rel 9.2), I encountered a problem that my code does not terminate for a big integer value.
First, I tested the following code, which processes both positive and negative values:
(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
The calls (assert (equal? #f (even? 100000000001)))
and (assert (equal? #t (odd? -100000000001)))
do not terminate on my machine, while, e.g. (assert (equal? #f (even? 1001)))
and (assert (equal? #t (odd? -1001)))
do.
My first thought was that the code is not optimized for proper tail recursion, while I have not one, but two tail calls in each function.
So, I decided to simplify the task and make a take for positive integers only, like this:
(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
But this version does not return either for big integers. So, I have these related questions:
- Features. Are mutually recursive functions in MIT/GNU Scheme optimized at all?
- Diagnostics. Is there any way one can tell the functions were indeed optimized for mutual tail recursion by Scheme compiler/interpreter. So, how can one tell the problem is in (absence of) tail recursion optimization, or in some other thing.
- What is proper mutual tail recursion? Does my initial code qualify for optimization? Does my second take qualify for it?