# NOT RUN {
## standard recursive function exhausts stack:
print_numbers <- function(n) {
if(n >= 1) {
print_numbers(n - 1)
print(n)
}
}
try(print_numbers(5000))
## use trampoline with a coro generator instead
print_numbers <- coro::generator(function(n) {
if(n >= 1) {
yield(print_numbers(n - 1))
print(n)
}
})
nums <- capture.output(
trampoline(print_numbers(5000))
)
cat(tail(nums))
## Or just use a plain function (but still use yield())
print_numbers <- function(n) {
if(n >= 1) {
yield(print_numbers(n - 1))
print(n)
}
}
trampoline(print_numbers(5))
## use an alias or another
tramampoline(print_numbers(5))
trambopoline(print_numbers(5))
## use multiple mutually recursive functions
even <- function(n) {
if (n == 0) trm_return(TRUE) else yield(odd(n - 1))
}
odd <- function(n) {
if (n == 0) trm_return(FALSE) else yield(even(n - 1))
}
## doesn't work (you must pass odd in because trampoline
## only converts first called function to generator by default)
try(trampoline(even(100)))
## does work
trampoline(even(100), odd = odd)
## you can specify your recursive function in the trampoline
## call if you want.
## Return a value using trm_return():
trampoline(factorial(13),
factorial = function(n) {
if(n <= 1) {
return(trm_return(1))
}
val <- yield(factorial(n - 1))
return(val * n)
})
## convert to using tail call optimization by wrapping
## recursive call in trm_tailcall()
trampoline(factorial(13),
factorial = function(n, x = 1) {
force(x) ## necessary thanks to R's lazy evaluation
if(n <= 1) {
return(trm_return(x))
}
val <- trm_tailcall(factorial(n - 1, x * n))
return(val)
})
# }
Run the code above in your browser using DataLab