我的全局环境中有一个名为myList
的变量。我有一个修改myList
的函数,并将其重新分配给名为myFunction
的全局环境。我只希望myList
修改myFunction
。有没有办法阻止任何其他功能修改myList
?
对于后台,我正在为R用户构建一个通用工具。我不希望该工具的用户能够定义自己的功能来修改myList
。我也不希望自己能够使用我将来可能编写的函数修改myList
。
我有一个潜在的解决方案,但我不喜欢它。执行该工具时,我可以检查用户定义的每个函数的文本,并搜索将myList
分配给全局环境的文本。我不喜欢我需要搜索所有功能的事实。
有人知道我在寻找的东西是否可以在R中实现?感谢您提供的任何帮助。
可重复的例子。我需要能够使以下示例成为可能的代码:
assign('myList', list(), envir = globalenv())
myFunction <- function() {
myList <- c(myList, 'test')
assign('myList', myList, envir = globalenv())
}
userFunction <- function() {
myList <- c(myList, 'test')
assign('myList', myList, envir = globalenv())
}
myFunction() # I need some code that will allow this function to run successfully
userFunction() # and cause an error when this function runs
答案 0 :(得分:1)
听起来你需要modules
包。
基本上,每个代码单元都有自己的范围。
e.g。
# install.packages("modules")
# Load library
library("modules")
# Create a basic module
m <- module({
.myList <- list()
myFunction <- function() {
.myList <<- c(.myList, 'test')
}
get <- function() .myList
})
# Accessor
m$get()
# list()
# Your function
m$myFunction()
# Modification
m$get()
# [[1]]
# [1] "test"
注意,我们通过将变量名称从.myList
更改为myList
来略微调整示例。因此,我们需要在userfunction()
userFunction <- function() {
.myList <- c(.myList, 'test')
}
运行这个,我们现在得到:
userFunction()
# Error in userFunction() : object '.myList' not found
根据需要。
有关更详细的示例,请参阅modules
vignette。
另一种方法是您可以定义一个环境(new.env()
),然后在加载myList
后将其锁定。
答案 1 :(得分:1)
这是一个坏主意。从分配到全局环境开始(我永远不会使用这样做的包)让您的用户感到惊讶。您应该只使用S4或引用类。
无论如何,您可以锁定绑定(如果您遵循更好的做法,则可以锁定环境)。您不会停止使用它的高级用户,但他们至少知道您不希望他们更改对象。
createLocked <- function(x, name, env) {
assign(name, x, envir = env)
lockBinding(name, env)
invisible(NULL)
}
createLocked(list(), "myList", globalenv())
myFunction <- function() {
unlockBinding("myList", globalenv())
myList <- c(myList, 'test')
assign('myList', myList, envir = globalenv())
lockBinding("myList", globalenv())
invisible(NULL)
}
userFunction <- function() {
myList <- c(myList, 'test')
assign('myList', myList, envir = globalenv())
}
myFunction() # runs successfully
userFunction()
#Error in assign("myList", myList, envir = globalenv()) :
# cannot change value of locked binding for 'myList'