使 R 函数 return 成为 locked/immutable 列表

make R function return a locked/immutable list

我有一个 return 列表的功能。 我希望这个列表是不可变的,类似于 lockBinding 防止覆盖或编辑对象的方式。

这看起来像下面这样:

myfun <- function(x){
    out <- list(a = 1, val = x)
    make_read_only(out)
    out
}
test <- myfun(9)
test$a
[1] 1

test$val
[1] 9

test
$a
[1] 1

$val
[1] 9

test$newval <- 7
Error:

其中 make_read_only() 只是一个函数或完成此任务的一些代码的替代。

我已经尝试使用 lockBinding,它可以完美地工作,但是 'lock' 在函数 return 输出后无法向上传递到父环境。 我也研究过尝试在父环境中锁定符号,但似乎没有办法从函数内部了解输出将分配给什么,而这需要作为 lockBinding 的参数。

似乎有一种方法可以通过 return 引用环境并使用 lockEnvironment() 锁定环境或做类似的事情来做到这一点,但我想听听有哪些选择在开始之前在那里完成这个。 类似地,使用 R6 似乎可以实现,但我宁愿避免使用 R6,因为此代码库的任何其他部分都不需要它,而且我只想听听有哪些选项可以实现此行为。

总之,该函数会return一个任意列表。此列表将至少有几层深度。

mylist <- myfun(list(b = list(c = 3), foo = "bar"))

用户应该能够以类似于当前美元符号访问

的直接方式访问 sublits/elements
mylist$a$b$c
[1] 3

应该不能编辑这个对象。

mylist$a <- 5
Error:

应该可以通过

删除对象
rm(mylist)
mylist
Error: object 'mylist' not found

所以我的问题是,R 中有哪些可用选项可以完成此操作?

实现此目的的一种方法是创建一个新的 class (locked) 以及 [<-[[<-$<- 的方法对于这个新 class,这将 return 一个错误。

例如:

`[[<-.locked` <- function(...) {stop("Can't assign into locked object")}
a<-list(a="a",b=2)
a
  $a
  [1] "a"

  $b
  [1] 2

class(a)<-"locked"
a[[1]]<-"moose"
  Error in `[[<-.locked`(`*tmp*`, 1, value = "moose") : 
    Can't assign into locked object

a
  $a
  [1] "a"

  $b
  [1] 2

  attr(,"class")
  [1] "locked"

在这种情况下,您的 "make read only" 函数需要做的就是将对象的 class 重新定义为 locked:

class(out)<-c("locked",class(out))