Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Eval function not loading libraries in R

Tags:

r

I am currently facing an issue with the eval function in R. In my real code, I have multiple libraries being loaded, but for simplicity, I will use data.table as an example.

Here is a snippet of my code:

test_code <- "library(data.table); data.table(iris)"
new_env <- new.env(parent = baseenv())
eval(parse(text = test_code), envir = new_env)

When I run this code, I get the following error:

Error in data.table(iris) : could not find function "data.table"

It seems like the eval function is not loading the data.table library in the new environment. I am not sure why this is happening as I expected the library to be loaded and the data.table function to be available in the new environment.

It's important to note that while this simplified example requires loading only one library, my actual project involves a significantly more complex and lengthy R test_code, with numerous libraries being loaded. As I cannot predict which libraries will need to be loaded, I would prefer if they could be automatically loaded upon evaluating the code.


Edit
The goal is to test if a codebase that is in principle self-sufficient operates correctly in a completely new environment. In other words, that it works from scratch.

More context:

I'm developing a Shiny app for data cleaning that also creates R code to replicate all actions performed in the app, including library loading. My aim is to test and evaluate this R code to verify if the resulting cleaned dataset matches the one from the Shiny app. Since the R code is generated dynamically, I don't know its contents in advance. Finally, I need to access and compare the cleaned dataset produced by the R code (accessible via new_env$DT) with the one generated through the app. The code replicate testing should be performed withing the Shiny app.

like image 924
mat Avatar asked Jun 27 '26 23:06

mat


1 Answers

The problem is that your new_env environment has its parent set to baseenv(), and the parent of baseenv() is empty. You didn't put any objects into new_env, so when you evaluate your expression in that environment, only objects in baseenv() will be found. library() is a function in the base environment, so that doesn't trigger an error, but library() modifies the search list, not the base environment, so data.table() will never be found.

To know what to do to fix your code, I'd need to know what you intend it to do.

  • If you just want access to the data.table function, you could leave the new_env definition as it is, but execute data.table::data.table(iris).

  • If you want the side effect of attaching data.table to the search list and want to evaluate your expression without the prefix, you could set the parent to globalenv() instead. However, that would allow a user to put a function named data.table into the global environment and it would take precedence over the one in the data.table package.

  • If you want the side effect of changing the search list but want to skip over the global environment, I think it's messy: the first entry in the search list is the parent of globalenv(), but library(data.table) might change that. So you could use library(data.table, pos = 3), but if you want to execute exactly the code you showed us, I think you can't do it with a single specification for envir. You'd need to parse the code and evaluate the expressions one at a time, each one using envir = parent.env(globalenv()). For example:

test_code <- "library(data.table); print(data.table(iris))"

new_env <- new.env(parent = parent.env(globalenv()))

exprs <- parse(text = test_code)

for (i in seq_along(exprs)) {
  eval(exprs[[i]], envir = new_env)
  parent.env(new_env) <- parent.env(globalenv())
}

You said in a comment that "The code is supposed to be self-sufficient, so the idea is to test the code in a completely new environment and ensure that everything works as intended." In that case, I wouldn't use my sample code, which evaluates it in a very strange way. You should do what R CMD check does, which is to start a new R process to run the tests by sourcing a file holding the code.