DOC HOME SITE MAP MAN PAGES GNU INFO SEARCH PRINT BOOK
 

(r5rs.info.gz) Proper tail recursion

Info Catalog (r5rs.info.gz) Storage model (r5rs.info.gz) Basic concepts
 
 3.5 Proper tail recursion
 =========================
 
 Implementations of Scheme are required to be _properly tail-recursive_.  Procedure
 calls that occur in certain syntactic contexts defined below are `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
 calls that may be returned from either by the current continuation or
 by 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 [propertailrecursion].
 
      _Rationale:_
 
      Intuitively, no space is needed for an active tail call because the
      continuation that is used in the tail call has the same semantics
      as the continuation passed to the procedure containing the call.
      Although an improper implementation might use a new continuation
      in the call, a return to this new continuation would be followed
      immediately by a return to the continuation passed to the
      procedure.  A properly tail-recursive implementation returns to
      that continuation directly.
 
      Proper tail recursion was one of the central ideas in Steele and
      Sussman's original version of Scheme.  Their first Scheme
      interpreter implemented both functions and actors.  Control flow
      was expressed using actors, which differed from functions in that
      they passed their results on to another actor instead of returning
      to a caller.  In the terminology of this section, each actor
      finished with a tail call to another actor.
 
      Steele and Sussman later observed that in their interpreter the
      code for dealing with actors was identical to that for functions
      and thus there was no need to include both in the language.
 
 
 A _tail call_ is a procedure call that occurs in a _tail context_.
 Tail contexts are defined inductively.  Note that a tail context is
 always determined with respect to a particular lambda expression.
 
    * The last expression within the body of a lambda expression, shown
      as <tail expression> below, occurs in a tail context.
 
      (lambda <formals>
        <definition>* <expression>* <tail expression>)
 
    * If one of the following expressions is in a tail context, then the
      subexpressions shown as <tail expression> are in a tail context.
      These were derived from rules in the grammar given in chapter
       Formal syntax and semantics by replacing some occurrences
      of <expression> with <tail expression>.  Only those rules that
      contain tail contexts are shown here.
 
      (if <expression> <tail expression> <tail expression>)
      (if <expression> <tail expression>)
 
      (cond <cond clause>+)
      (cond <cond clause>* (else <tail sequence>))
 
      (case <expression>
        <case clause>+)
      (case <expression>
        <case clause>*
        (else <tail sequence>))
 
      (and <expression>* <tail expression>)
      (or <expression>* <tail expression>)
 
      (let (<binding spec>*) <tail body>)
      (let <variable> (<binding spec>*) <tail body>)
      (let* (<binding spec>*) <tail body>)
      (letrec (<binding spec>*) <tail body>)
 
      (let-syntax (<syntax spec>*) <tail body>)
      (letrec-syntax (<syntax spec>*) <tail body>)
 
      (begin <tail sequence>)
 
      (do (<iteration spec>*)
          (<test> <tail sequence>)
        <expression>*)
 
      where
 
      <cond clause> -> (<test> <tail sequence>)
      <case clause> -> ((<datum>*) <tail sequence>)
 
      <tail body> -> <definition>* <tail sequence>
      <tail sequence> -> <expression>* <tail expression>
 
    * If a `cond' expression is in a tail context, and has a clause of
      the form `(<expression1> => <expression2>)' then the (implied)
      call to the procedure that results from the evaluation of
      <expression2> is in a tail context.  <expression2> itself is not
      in a tail context.
 
 
 Certain built-in procedures are also required to perform tail calls.
 The first argument passed to `apply' and to `call-with-current-continuation',
 and the second argument passed to `call-with-values', must be called
 via a tail call.  Similarly, `eval' must evaluate its argument as if it were
 in tail position within the `eval' procedure.  
 
 In the following example the only tail call is the call to `f'.  None
 of the calls to `g' or `h' are tail calls.  The reference to `x' is in
 a tail context, but it is not a call and thus is not a tail call.
 
 
      (lambda ()
        (if (g)
            (let ((x (h)))
              x)
            (and (g) (f))))
 
      _Note:_ Implementations are allowed, but not required, to
      recognize that some non-tail calls, such as the call to `h' above,
      can be evaluated as though they were tail calls.  In the example
      above, the `let' expression could be compiled as a tail call to
      `h'. (The possibility of `h' returning an unexpected number of
      values can be ignored, because in that case the effect of the
      `let' is explicitly unspecified and implementation-dependent.)
 
Info Catalog (r5rs.info.gz) Storage model (r5rs.info.gz) Basic concepts
automatically generated byinfo2html