drake-r-package

Use a dedicated environment for drake, with r_make()


I'm trying to adapt the recommendation in Section 12.7.6.5 of the manual of using a dedicated environment (rather than the global environment) to interactive usage with r_make().

What I did is to modify the _drake.R configuration script as follows:

envir <- new.env(parent = globalenv())
source("R/packages.R", local = envir)  # Load your packages, e.g. library(drake).
source("R/functions.R", local = envir) # Define your custom code as a bunch of functions.
source("R/plan.R", local = envir)      # Create your drake plan.
drake_config(plan, envir = envir)

for any packages, functions and plan. When I run

library(drake)
r_make()

I get:

Error in if (nrow(plan) < 1L) { : argument is of length zero

Error: <callr_status_error: callr subprocess failed: argument is of length zero>
-->
<callr_remote_error in if (nrow(plan) < 1L) { ...:
 argument is of length zero>
 in process 1598 

See `.Last.error.trace` for a stack trace.

Am I missing something?


Solution

  • If you are already using r_make(), you most likely do not need to bother with envir. Because r_make() begins and ends in its own isolated callr::r() process, the global environment of the master session is already protected. In fact, r_make() is much better than envir when it comes to environment reproducibility, so you are already on the right track.

    But if you do still want to use envir, please make sure the plan is defined in the environment that calls drake_config(): that is, the global environment of the session that runs _drake.R. So you can either call drake_config(envir$plan, envir = envir) or write source("plan.R") instead of source("plan.R", local = envir).

    Examples:

    writeLines(
      c(
        "library(drake)",
        "plan <- drake_plan(x = 1)"  
      ),
      "plan.R"
    )
    writeLines(
      c(
        "envir <- new.env(parent = globalenv())",
        "source(\"plan.R\", local = envir)",
        "ls() # does not contain the plan",
        "ls(envir) # contains the plan",
        "drake_config(envir$plan, envir = envir)"
      ),
      "_drake.R"
    )
    
    cat(readLines("plan.R"), sep = "\n")
    #> library(drake)
    #> plan <- drake_plan(x = 1)
    
    cat(readLines("_drake.R"), sep = "\n")
    #> envir <- new.env(parent = globalenv())
    #> source("plan.R", local = envir)
    #> ls() # does not contain the plan
    #> ls(envir) # contains the plan
    #> drake_config(envir$plan, envir = envir)
    
    library(drake)
    r_make()
    #> [32mtarget[39m x
    

    Created on 2020-01-13 by the reprex package (v0.3.0)

    writeLines(
      c(
        "library(drake)",
        "plan <- drake_plan(x = 1)"  
      ),
      "plan.R"
    )
    writeLines(
      c(
        "envir <- new.env(parent = globalenv())",
        "source(\"plan.R\") # source into global envir",
        "ls()",
        "ls(envir)",
        "drake_config(plan, envir = envir)"
      ),
      "_drake.R"
    )
    
    cat(readLines("plan.R"), sep = "\n")
    #> library(drake)
    #> plan <- drake_plan(x = 1)
    
    cat(readLines("_drake.R"), sep = "\n")
    #> envir <- new.env(parent = globalenv())
    #> source("plan.R") # source into global envir
    #> ls()
    #> ls(envir)
    #> drake_config(plan, envir = envir)
    
    library(drake)
    r_make()
    #> [32mtarget[39m x
    

    Created on 2020-01-13 by the reprex package (v0.3.0)