没有包的命名空间 [英] Namespaces without packages

查看:91
本文介绍了没有包的命名空间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在重新组织代码库时,我想清理代码共享机制.到目前为止,我将source用于许多小型的,功能齐全的功能模块.

In reorganising my code base I’d like to clean up my code sharing mechanism. So far I’m using source for lots of small, largely self-contained modules of functionality.

但是,这种方法存在许多问题,其中

However, this approach suffers from a number of problems, among them

  • 缺乏圆度测试(偶然的圆形source链),
  • 正确指定包含路径(chdir=TRUE参数,硬编码路径)所需的
  • 复杂语法,
  • 潜在的名称冲突(重新定义对象时).
  • the lack of tests for circularity (accidental circular source chains),
  • complex syntax required to properly specify include paths (chdir=TRUE argument, hard-coded paths),
  • potential of name clashes (when redefining objects).

理想情况下,我想对Python模块机制有所帮助. R包机制在这里可能会过大:不是想要生成嵌套的路径层次结构,包含大量元数据的多个文件并手动构建包只是为了获得一个小的,独立的可重用代码模块.

Ideally I’d like to get something alike to the Python module mechanism. The R package mechanism would be overkill here: I do not want to generate nested path hierarchies, multiple files with tons of metadata and manually build the package just to get a small, self-contained, reusable code module.

目前,我正在使用一个代码段,该代码段可以解决上面提到的前两个问题.包含的语法如下:

For now I’m using a code snippet which allows me to solve the first two problems mentioned above. The syntax for inclusion is like this:

import(functional)
import(io)
import(strings)

…,并且将模块定义为驻留在本地路径中的简单源文件. import的定义很简单,但我无法解决第三点:我想导入模块进入一个单独的命名空间,但从我的观察来看,命名空间查找机制非常牢固地连接到包.没错,我可以覆盖`::`getExportedValue以及asNamespaceisNamespace,但这听起来很脏,并且有可能破坏其他软件包.

… and a module is defined as a simple source file which resides in the local path. The definition of import is straightforward but I cannot solve the third point: I want to import the module into a separate namespace but from what I see the namespace lookup mechanism is pretty hard-wired to packages. True, I could override `::` or getExportedValue and maybe asNamespace and isNamespace but that feels very dirty and has the potential of breaking other packages.

推荐答案

这是一个完全自动化程序包创建,编译和重新加载的功能.正如其他人指出的那样,实用程序功能package.skeleton()devtools::load_all()已经使您几乎一直存在.这只是结合了它们的功能,使用package.skeleton()在临时目录中创建源目录,当load_all()处理完该目录时,该目录将被清除.

Here's a function that completely automates package creation, compilation, and reloading. As others have noted, the utility functions package.skeleton() and devtools::load_all() already get you almost all the way there. This just combines their functionality, using package.skeleton() to create the source directory in a temp directory that gets cleaned up when load_all() is done processing it.

您需要做的只是指向要从中读取函数的源文件,并为程序包命名:import()为您完成其余的工作.

All you need to do is point to the source files from which you want to read in functions, and give the package a name: import() does the rest for you.

import <- function(srcFiles, pkgName) {
    require(devtools)
    dd <- tempdir()
    on.exit(unlink(file.path(dd, pkgName), recursive=TRUE))
    package.skeleton(name=pkgName, path = dd, code_files=srcFiles)
    load_all(file.path(dd, pkgName))
}

## Create a couple of example source files
cat("bar <- function() {print('Hello World')}", file="bar.R")
cat("baz <- function() {print('Goodbye, cruel world.')}", file="baz.R")

## Try it out
import(srcFiles=c("bar.R", "baz.R"), pkgName="foo")

## Check that it worked
head(search())
# [1] ".GlobalEnv"        "package:foo"       "package:devtools"
# [4] "package:stats"     "package:graphics"  "package:grDevices"
bar()
# [1] "Hello World"
foo::baz()
# [1] "Goodbye, cruel world."

这篇关于没有包的命名空间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆