限制哪些函数可以修改对象

时间:2017-01-10 04:06:15

标签: r

我的全局环境中有一个名为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

2 个答案:

答案 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'