Tail recursion is the act of making a tail recursive call.
We can understand that term in parts.
A call is just application of a function.
A recursive call occurs when a function invokes itself.
A tail call occurs when a function's result is just the value of
another function call. In other words, in order to determine the value of
function
Why to use tail calls?
For a non-tail call, Scheme must remember that after the current function application, it is responsible for doing something else (in this case, adding 1 to the result); and there may be many such things to do. For a tail call, Scheme doesn't have to remember anything, because there is nothing more to do: after it is done with the current function call, it is really done.
Non-tail calls force Scheme to remember future actions (that couldn't be performed before), but tail calls don't. Non-tail calls require more space (because there is more to remember), so they are not as efficient as tail calls. Tail calls also permit us to forget the values of function parameters and local variables, because we never do any more work in the calling function, but a non-tail call forces us to remember such values, which might be used when we return to the calling function.
f
, we call g
, and return whatever g
did, without modification.Why to use tail calls?
For a non-tail call, Scheme must remember that after the current function application, it is responsible for doing something else (in this case, adding 1 to the result); and there may be many such things to do. For a tail call, Scheme doesn't have to remember anything, because there is nothing more to do: after it is done with the current function call, it is really done.
Non-tail calls force Scheme to remember future actions (that couldn't be performed before), but tail calls don't. Non-tail calls require more space (because there is more to remember), so they are not as efficient as tail calls. Tail calls also permit us to forget the values of function parameters and local variables, because we never do any more work in the calling function, but a non-tail call forces us to remember such values, which might be used when we return to the calling function.
(define foo (lambda (x) (if (even? x) (+ 1 (foo (/ x 2))) (bar x)))) (define bar (lambda (y) (* y 3)))
The definition of
foo
contains a recursive call to foo
(it's recursive because foo
is the procedure in which the call to
foo
appears) and a tail call to bar
. The call to
bar
is a tail call because, if the parameter x
is even,
then the value of the call of foo
is just whatever bar
returns.
Its new, it is good.
ReplyDelete