Answers:
这是一种可能的方法。使用该exists
功能检查util.R
代码中是否有独特的内容。
例如:
if(!exists("foo", mode="function")) source("util.R")
(mode="function"
如Gavin Simpson所指出,被编辑为包括在内)
exists()
-需要mode = "function"
添加以使其变得更加简单
exists()
除了在R 3.0.2中返回一个错误外,似乎抛出一个错误。
没有内置的东西,因为R不会跟踪对调用的调用source
,也无法弄清楚从何处加载了什么(使用包时不是这种情况)。但是,您可能会使用与C .h
文件中相同的想法,即将整个文件包装在:
if(!exists('util_R')){
util_R<-T
#Code
}
source("util.R")
在if
代码内调用,对吗?
说util.R
产生功能foo()
。您可以检查此功能在全局环境中是否可用,如果不可用,请提供脚本源:
if(identical(length(ls(pattern = "^foo$")), 0))
source("util.R")
那会发现任何带有名称的东西foo
。如果您想找到一个函数,那么(如@Andrie所提到的)exists()
很有用,但需要准确告知要查找的对象类型,例如
if(exists("foo", mode = "function"))
source("util.R")
这里正在exists()
起作用:
> exists("foo", mode = "function")
[1] FALSE
> foo <- function(x) x
> exists("foo", mode = "function")
[1] TRUE
> rm(foo)
> foo <- 1:10
> exists("foo", mode = "function")
[1] FALSE
grepl(..., value=TRUE)
因为您的搜索词可能不是正则表达式。+1,顺便说一句。
grepl()
没有论据value
,但我可能应该修复正则表达式中ls()
...
fixed=TRUE
exists()
更好,但现在我看到您同时发布了这样的答案。
您可以编写一个使用文件名和环境名称的函数,检查文件是否已加载到环境中,sys.source
如果没有,则使用该函数来获取文件。
这是一个快速且未经测试的功能(欢迎改进!):
include <- function(file, env) {
# ensure file and env are provided
if(missing(file) || missing(env))
stop("'file' and 'env' must be provided")
# ensure env is character
if(!is.character(file) || !is.character(env))
stop("'file' and 'env' must be a character")
# see if env is attached to the search path
if(env %in% search()) {
ENV <- get(env)
files <- get(".files",ENV)
# if the file hasn't been loaded
if(!(file %in% files)) {
sys.source(file, ENV) # load the file
assign(".files", c(file, files), envir=ENV) # set the flag
}
} else {
ENV <- attach(NULL, name=env) # create/attach new environment
sys.source(file, ENV) # load the file
assign(".files", file, envir=ENV) # set the flag
}
}
这是我编写的函数。它包装了base::source
将源文件列表存储在名为的全局环境列表中的函数sourced
。仅当您提供.force=TRUE
对源调用的参数时,它才会重新获得文件。否则,其参数签名与真实参数相同,source()
因此您无需重写脚本即可使用它。
warning("overriding source with my own function FYI")
source <- function(path, .force=FALSE, ...) {
library(tools)
path <- tryCatch(normalizePath(path), error=function(e) path)
m<-md5sum(path)
go<-TRUE
if (!is.vector(.GlobalEnv$sourced)) {
.GlobalEnv$sourced <- list()
}
if(! is.null(.GlobalEnv$sourced[[path]])) {
if(m == .GlobalEnv$sourced[[path]]) {
message(sprintf("Not re-sourcing %s. Override with:\n source('%s', .force=TRUE)", path, path))
go<-FALSE
}
else {
message(sprintf('re-sourcing %s as it has changed from: %s to: %s', path, .GlobalEnv$sourced[[path]], m))
go<-TRUE
}
}
if(.force) {
go<-TRUE
message(" ...forcing.")
}
if(go) {
message(sprintf("sourcing %s", path))
.GlobalEnv$sourced[path] <- m
base::source(path, ...)
}
}
非常健谈(有很多呼叫message()
),因此您可以在需要时删除这些行。感谢资深R用户的任何建议;我是R的新手。
我使用代码所在的整个地址解决了我的问题:之前:
if(!exists("foo", mode="function")) source("utils.r")
后:
if(!exists("foo", mode="function")) source("C:/tests/utils.r")