[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

doc tail calls

From: Kevin Ryde
Subject: doc tail calls
Date: Sat, 12 Feb 2005 09:21:43 +1100
User-agent: Gnus/5.110003 (No Gnus v0.3) Emacs/21.3 (gnu/linux)

This is some words about tail calls, with I don't think are otherwise
described.  I'm thinking of this for a new section just after the
"Evaluating" node.

3.1.5 Tail calls

Scheme is "properly tail recursive", meaning that tail calls or
recursions from certain contexts do not consume stack space or other
resources and can therefore be used on arbitrarily large data or for an
arbitrarily long calculation.  Consider for example,

     (define (foo n)
       (display n)
       (foo (1+ n)))

     (foo 1)

   `foo' prints numbers infinitely, starting from the given N.  It's
implemented by printing N then recursing to itself to print N+1 and so
on.  This recursion is a tail call, it's the last thing done, and in
Scheme such tail calls can be made without limit.

   Or consider a case where a value is returned, a version of the SRFI-1
`last' function (*note SRFI-1 Selectors::) returning the last element
of a list,

     (define (my-last lst)
       (if (null? (cdr lst))
           (car lst)
           (my-last (cdr lst))))

     (my-last '(1 2 3)) => 3

   If the list has more than one element, `my-last' applies itself to
the `cdr'.  This recursion is a tail call, there's no code after it,
and the return value is the return value from that call.  In Scheme
this can be used on an arbitrarily long list argument.

   A proper tail call is only available from certain contexts, namely
the following special form positions,

   * `and' -- last expression

   * `begin' -- last expression

   * `case' -- last expression in each clause

   * `cond' -- last expression in each clause, and the call to a `=>'
     procedure is a tail call

   * `do' -- last result expression

   * `if' -- "true" and "false" leg expressions

   * `lambda' -- last expression in body

   * `let', `let*', `letrec', `let-syntax', `letrec-syntax' -- last
     expression in body

   * `or' -- last expression

The following core functions make tail calls,

   * `apply' -- tail call to given procedure

   * `call-with-current-continuation' -- tail call to the procedure
     receiving the new continuation

   * `call-with-values' -- tail call to given procedure

   * `eval' -- tail call to evaluate the form

   * `string-any', `string-every' -- tail call to predicate on the last
     character (if that point is reached)

   The above are just the core functions and special forms, tail calls
in other modules are described with the relevant documentation, for
example SRFI-1 `any' and `every' (*note SRFI-1 Searching::).

   It will be noted there are a lot of places which could potentially be
tail calls, for instance the last call in a `for-each', but only those
explicitly described are guaranteed.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]