Rev 85997 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
% File src/library/base/man/Tailcall.Rd% Part of the R package, https://www.R-project.org% Copyright 1995-2023 R Core Team% Distributed under GPL 2 or later\name{Tailcall}\alias{Tailcall}\alias{Exec}\title{\code{Tailcall} and \code{Exec}}\description{\code{Tailcall} and \code{Exec} allow writing morestack-space-efficient recursive functions in \R.}\usage{Tailcall(FUN, \dots)Exec(expr, envir)}\arguments{\item{FUN}{a function or a non-empty character string naming thefunction to be called.}\item{\dots}{all the arguments to be passed.}\item{expr}{a call expression.}\item{envir}{environment for evaluating \code{expr}; default is theenvironment from which \code{Exec} is called.}}\details{\code{Tailcall} evaluates a call to \code{FUN} with arguments \dots inthe current environment, and \code{Exec} evaluates the call\code{expr} in environment \code{envir}. If a \code{Tailcall} or\code{Exec} expression appears in tail position in an \R function, andif there are no \code{on.exit} expressions set, then the evaluationcontext of the new calls replaces the currently executing call contextwith a new one. If the requirements for context re-use are not met,then evaluation proceeds in the standard way adding another context tothe stack.Using \code{Tailcall} it is possible to define tail-recursivefunctions that do not grow the evaluation stack. \code{Exec} can beused to simplify the call stack for functions that create and thenevaluate an expression.Because of lazy evaluation of arguments in \R it may be necessary toforce evaluation of some arguments to avoid accumulating deferredevaluations.This \emph{tail call optimization} has the advantage of not growingthe call stack and permitting arbitrarily deep tail recursions. Itdoes also mean that stack traces produced by \code{\link{traceback}}or \code{\link{sys.calls}} will only show the call specified by\code{Tailcall} or \code{Exec}, not the previous call whose stackentry has been replaced.}\note{\code{Tailcall} and \code{Exec} are experimental and may bechanged or dropped in future released versions of \R.}\seealso{\code{\link{Recall}} and \code{\link{force}}.}\examples{## tail-recursive log10-factoriallfact <- function(n) {lfact_iter <- function(val, n) {if (n <= 0)valelse {val <- val + log10(n) # forces valTailcall(lfact_iter, val, n - 1)}}lfact_iter(0, n)}10 ^ lfact(3)lfact(100000)## simplified variant of do.call using Exec:docall <- function (what, args, quote = FALSE) {if (!is.list(args))stop("second argument must be a list")if (quote)args <- lapply(args, enquote)Exec(as.call(c(list(substitute(what)), args)), parent.frame())}## the call stack does not contain the call to docall:docall(function() sys.calls(), list()) |>Find(function(x) identical(x[[1]], quote(docall)), x = _)## contrast to do.call:do.call(function(x) sys.calls(), list()) |>Find(function(x) identical(x[[1]], quote(do.call)), x = _)}\keyword{programming}