使用addTaskCallback()
中的示例作为模板,我进行了以下操作.它使用times()
参数来标识额外的回调将运行多少次(我目前已将其设置为Inf
,因此您必须使用removeTaskCallback()
将其关闭.它目前所做的是判断环境中在任务执行前后是否有相同的名称.然后,如果这些对象中的任何一个已更改,它将返回一条消息.下面是一个例子:
times <- function(total = Inf, before_env = as.list(.GlobalEnv)) {
ctr <- 0
function(expr, value, ok, visible) {
check_environment_overwrite <- function(before_env) {
after_env <- as.list(.GlobalEnv)
olaps <- intersect(names(before_env), names(after_env))
if(length(olaps) > 0){
if(!identical(before_env[olaps], after_env[olaps])){
out <- lapply(seq_along(olaps), \(i){
identical(before_env[[olaps[i]]],
after_env[[olaps[i]]])})
outv <- do.call("c", out)
names(outv) <- olaps
cat("The following elements have changed in .GlobalEnv: ",
names(outv)[which(!outv)], "\n", sep="")
}
}
}
check_environment_overwrite(before_env)
before_env <<- as.list(.GlobalEnv)
ctr <<- ctr + 1
keep.me <- (ctr < total)
if (!keep.me)
cat("handler removing itself\n")
# return
keep.me
}
}
要获得相同的结果,请从不包括x
或z
的工作区开始:
# > n <- addTaskCallback(times())
# > x <- 1
# > z <- 1
# > x <- 2
# The following elements have changed in .GlobalEnv: x
# > z <- 1
# > z <- 2
# The following elements have changed in .GlobalEnv: z
# >
# > removeTaskCallback(n)
# [1] TRUE
Edit: alternative assignment operator that checks overwriting beforehand
本着这个问题的精神,上面的函数将在您覆盖某些内容后通知您.我们可以使用另一个赋值操作符来查看某些内容是否会被覆盖,如果会,它会询问用户是否要覆盖它.
`%a%` <- function(lhs, rhs){
lhs_name <- as.character(substitute(lhs))
if(lhs_name %in% names(.GlobalEnv)){
rpl <- askYesNo(paste0("Do you want to replace ", lhs_name, " in .GlobalEnv"))
if(rpl){
assign(lhs_name, rhs, envir = .GlobalEnv)
}
}else{
assign(lhs_name, rhs, envir = .GlobalEnv)
}
}
# > x %a% 1
# > x %a% 2
# Do you want to replace x in .GlobalEnv (Yes/no/cancel) Yes
# > x
# [1] 2