首页 > 解决方案 > 包括 R 中的 carrier::crate 中的额外功能,R 中的手动环境创建

问题描述

我正在尝试使用carrier::crateR 创建独立函数,该函数可以在没有原始会话中的库但没有运气的情况下在环境(即 docker 容器)中导出。该示例是根据博客文章修改的。我以styler包为例。我遇到了继承依赖项的问题,可能这种 hack 不值得努力。

但是我想了解这里发生了什么。为什么import_env2在 crated 函数中找不到声明的函数?


第一个基于 R 的环境 ( docker run -it -v <repopath>:<repopath> r-base):

install.packages(c("styler", "pkgload", "carrier"))

# incude imported functions
import_env <- rlang::ns_imports_env("styler")
imported_functions_names <- ls(import_env)

imported_functions_to_declare <- lapply(
  imported_functions_names,
  function(x) rlang::expr(import_env[[!!x]])
)
names(imported_functions_to_declare) <- imported_functions_names

# declare package functions and data
pgk_path <- "<path_to_styler_source>"
package_name <- pkgload::pkg_name(pgk_path)
pkgload::load_all(pgk_path)
package_namespace_ls <- ls(getNamespace(package_name))

package_functions_to_set_env <- lapply(package_namespace_ls, function (x) {
  if(is.function(get(x))) rlang::expr(rlang::set_env(!!rlang::sym(x)))
})
names(package_functions_to_set_env) <- package_namespace_ls
package_functions_to_set_env <- package_functions_to_set_env[!sapply(package_functions_to_set_env,is.null)]

package_data_to_set_env <- lapply(package_namespace_ls, function (x) {
  if(!is.function(get(x))) rlang::expr(!!rlang::sym(x))
})
names(package_data_to_set_env) <- package_namespace_ls
package_data_to_set_env <- package_data_to_set_env[!sapply(package_data_to_set_env,is.null)]


# manually pick some functions that are not included in above list for some reason
# FIXME: why is this failing?
import_env2 <- rlang::env()
rlang::env_bind(import_env2, enquos = rlang::enquos)
rlang::env_bind(import_env2, quo_invert = purrr:::quo_invert)
extra_functions_names <- ls(import_env2)

extra_functions_to_declare <- lapply(
  extra_functions_names,
  function(x) rlang::expr(import_env2[[!!x]])
)
names(extra_functions_to_declare) <- extra_functions_names

# crate the function
fun <- carrier::crate(
  ~style_text(.x),
  !!!package_functions_to_set_env,
  !!!package_data_to_set_env,
  !!!imported_functions_to_declare,
  !!!extra_functions_to_declare
  )

# save crated function
save(fun, file = "<fun_file>")

干净的 R-base 环境(docker run -it -v <repopath>:<repopath> r-base):

> load("<fun_file>")
Warning: namespace ‘rlang’ is not available and has been replaced
by .GlobalEnv when processing object ‘fun’
Warning: namespace ‘tibble’ is not available and has been replaced
by .GlobalEnv when processing object ‘fun’
Warning: namespace ‘styler’ is not available and has been replaced
by .GlobalEnv when processing object ‘fun’
Warning: namespace ‘purrr’ is not available and has been replaced
by .GlobalEnv when processing object ‘fun’
Warning: namespace ‘pillar’ is not available and has been replaced
by .GlobalEnv when processing object ‘fun’
Warning: namespace ‘magrittr’ is not available and has been replaced
by .GlobalEnv when processing object ‘fun’
> fun("test")
Error in enquos(...) : could not find function "enquos"

标签: rdockerrlangcarrier

解决方案


推荐阅读