i see both of the following functions are syntactically tail recursive ones, but, in racket, which of them is really treated as tail recursion, or both? i mean whether it is optimized as tail recursion by the interpreter.
;;1
(define (foo i m s)
(if (< i m)
(foo (+ i 1) m (+ i s))
s))
;;2
(define (foo i m s)
(if (= i m)
s
(foo (+ i 1) m (+ i s))))
are there any different answers in other lisps?
Both are tail recursive by the fact that the recursive call is done in the tail position, that is to say: it's the last thing done when calling the recursion. It doesn't matter at all if the order of the consequent and alternative parts in the if
expression is reversed in the procedures shown.
And by Scheme's specification, all tail recursions must be optimized away, no mater where they appear in the code, syntactically speaking:
Implementations of Scheme must be properly tail-recursive. Procedure calls that occur in certain syntactic contexts called tail contextsare tail calls. A Scheme implementation is properly tail-recursive if it supports an unbounded number of active tail calls. A call is active if the called procedure may still return. Note that this includes regular returns as well as returns through continuations captured earlier by call-with-current-continuation that are later invoked. In the absence of captured continuations, calls could return at most once and the active calls would be those that had not yet returned. A formal definition of proper tail recursion can be found in Clinger's paper [5]. The rules for identifying tail calls in constructs from the (rnrs base (6)) library are described in section 11.20.