Port of Python's contextlib.contextmanager. R has no yield, so instead of
suspending the function the body calls teardown() right after acquiring each
resource and returns the resource. From that one definition you get:
Details
a
local_form: the function itself. Cleanup runs when the calling function exits, likewithr::local_*().a
with_form:with_context()runs a block, then cleans up.a decorator:
as_decorator()runs a function inside the context.
The decorated function takes ..., passed on to the setup function, and a
.local_envir argument naming the frame whose exit triggers cleanup. It
defaults to the caller, or, when called from another context manager's setup,
to that context's .local_envir, so composed contexts last as long as the
outer one.
teardown(expr) registers expr with withr::defer() on that frame. Cleanups
run last in, first out, and the ones already registered still run if the rest
of the setup fails. teardown() finds the frame by searching the call stack
for the nearest running context manager and reading its .local_envir.
Examples
local_tempdir := contextmanager %@% function(pattern = "tmp") {
path <- tempfile(pattern)
dir.create(path)
teardown(unlink(path, recursive = TRUE))
path
}
f <- function() {
d <- local_tempdir()
writeLines("hi", file.path(d, "x.txt"))
d
}
d <- f()
dir.exists(d) # cleaned up when f() exited
#> [1] FALSE