knitr::opts_chunk$set( error = FALSE, collapse = TRUE, comment = "#>")
The idea here is that we want to describe how to build a "context" and then evaluate one or more expressions in it. This is a little related to approaches like docker
and packrat
in that we want contexts to be isolated from one another, but different in that portability is more important than isolation.
Imagine that you have an analysis to run on another computer with:
drat
, bioconductor, etc).The other computer may already have some packages installed, so you don't want to waste time and bandwidth re-installing them. So things end up littered with constructs like
if (!require("mypkg")) { install.packages("mypkg") library(mypkg) }
If these packages are coming from GitHub (or worse also have dependencies on GitHub) the bootstrap code gets out of hand very quickly and tends to be non-portable.
Creating separate libraries (rather than sharing one from your personal computer) will be important if the architecture differs (e.g., you run Windows but you want to run code on a Linux cluster).
The idea here is that context
helps describe a context made from the above ingredients and then attempts to recreate it on a different computer (or in a different directory on your computer).
A minimal context looks like this:
path <- tempfile() ctx <- context::context_save(path = path) ctx
Typically one would use the arguments packages
and sources
to describe the requirements of any tasks that you'll be running.
Once a context is defined, tasks can be defined in the context. These are simply R expressions associated with the identifier of a context.
t <- context::task_save(quote(sin(1)), context = ctx) t
The task t
above is just a key that can be used to retrieve information about the task later.
context::task_expr(t, ctx)
Several such tasks may exist, though here only one does
context::task_list(ctx)
To run a task we first need to "load" the context (this will actual load any required packages and source any scripts) then pass this through to task_run
res <- context::task_run(t, context::context_load(ctx))
This prints the result of restoring the context and running the task:
context
: the context idlibrary
: calls to library()
to load packages and attach namespacesnamespace
: calls to loadNamespace()
; these packages were present
but not attached in the context.source
: There was nothing to source()
here so this is blank,
otherwise it would be a list of filenames.root
: the directory within which all our context/task files will be
locatedcontext
: this is repeated here because we've finished the load part of the aove statementtask
: the task idexpr
: the expression to evaluatestart
: start timeok
: indication of successend
: end timeAfter all that, here is the result:
res
The result can also be retrieved using task_result()
:
context::task_result(t, ctx)
This is not immensely useful as it is; it's just evaluation with more steps. Typically we'd do this in another process. You can do this with callr
here:
res <- callr::rscript(file.path(path, "bin", "task_run"), c(path, t), echo = TRUE, show = TRUE)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.