有没有办法声明命名空间并将函数导出到其中,以便可以使用::
访问它,而无需创建整个包?
以下适用于:::
但不适用::
:
ns <- namespace::makeNamespace("my_namespace")
assign("test",7, env=ns)
my_namespace:::test # Triple colon - works.
# [1] 7
my_namespace::test # Double colon - doesn't work.
# Error: 'test' is not an exported object from 'namespace:my_namespace'
是否有替代assign
会使最后一行有效? (目标是能够在开发包时模拟包,因此其他文件可以使用它,就好像它是一个完整的包,但可以使用source
而不是devtools::install
快速重新加载。)< / p>
答案 0 :(得分:3)
base::namespaceExport(ns, ls(ns))
似乎有用(当然你也可以使用子集作为第二个参数中要导出的对象列表)。一旦定义了要导出的命名空间中的所有对象,就使用它:
ns <- namespace::makeNamespace("my_namespace")
assign("test", 7, env = ns)
base::namespaceExport(ns, ls(ns))
my_namespace::test
输出:
7
答案 1 :(得分:1)
您可能会发现以下内容对于加快软件包开发的预期用例非常有用:
http://stat.ethz.ch/R-manual/R-patched/library/utils/html/getFromNamespace.html
说明
实用程序用于访问和替换命名空间中的非导出函数,以用于开发具有命名空间的包。
答案 2 :(得分:1)
我有相同的用例,并设计了这个:
#' simulate a package
#'
#' simulate loading a namespace or attaching a package. designed to make reprexes easy. The input function's closer env is set to
#' the namespace and no fancy feature such as registering S3 methods is supported
#'
#' @param name string, name of fake package
#' @param exported named list of exported functions
#' @param unexported named list of unexported functions
#' @param attach whether to attach the fake package
#'
#' @noRd
fake_package <- function(name, exported = NULL, unexported = NULL, attach = TRUE) {
# fetch and eval call to create `makeNamespace`
eval(body(loadNamespace)[[c(8, 4, 4)]])
# create an empty namespace
ns <- makeNamespace(name)
# makethis namespace the closure env of our input functions
exported <- lapply(exported, `environment<-`, ns)
unexported <- lapply(unexported, `environment<-`, ns)
# place these in the namespace
list2env(exported, ns)
list2env(unexported, ns)
# export relevant functions
namespaceExport(ns, names(exported))
if(attach) {
# copy exported funs to "package:pkg" envir of the search path
attach(exported, name = paste0("package:", name))
}
invisible()
}
以下是它的使用方法(这里我们将 attach
保留为默认的 TRUE
,因此我们在搜索路径上创建了一个 "package:fake"
环境):
fake_package(
"fake",
exported = list(add_2 = function(x) add_1(x) + 1),
unexported = list(add_1 = function(x) x + 1))
# the search path looks as it would after a library call
search()
#> [1] ".GlobalEnv" "package:fake" "package:stats"
#> [4] "package:graphics" "package:grDevices" "package:utils"
#> [7] "package:datasets" "package:methods" "Autoloads"
#> [10] "tools:callr" "package:base"
# add_2 was exported
add_2
#> function(x) add_1(x) + 1
#> <environment: namespace:fake>
fake::add_2
#> function(x) add_1(x) + 1
#> <environment: namespace:fake>
fake:::add_2
#> function(x) add_1(x) + 1
#> <environment: namespace:fake>
# add_1 was not, so as expected can't be found
add_1
#> Error: object 'add_1' not found
fake::add_1
#> Error: 'add_1' is not an exported object from 'namespace:fake'
fake:::add_1
#> function(x) x + 1
#> <environment: namespace:fake>
# let's try it
add_2(3)
#> [1] 5
解决方案是 100% 基础 R,eval(body(loadNamespace)[[c(8, 4, 4)]])
调用不是很优雅,如果代码更改可能会中断,您可以将其删除并用 ns <- namespace::makeNamespace(name)
替换下一行(如果取决于 { namespace} 包没问题。