如何防止 R6 类 访问不存在的成员?

How can I prevent R6 classes to access non-existent members?

R6 自动将我访问的任何内容设置为 NULL

> x <- R6::R6Class("x", list(foo = function() { print(self$notexistent) }))
> xx <- x$new()
> xx$foo()
NULL

这意味着如果我在一次访问中输入错误,例如results 而不是 result 它将使用 NULL 而不是抛出错误。有没有办法强制后者?

R6函数中的self是环境。环境的 $ 运算符是原始的,据我所知,它不能被覆盖。默认情况下,如果在环境中找不到 right-sided 操作数,此运算符 returns NULL 而不是抛出错误,并且此事实必须由调用者显式处理。

这与 C++ 中的 [ 运算符没有太大区别,它不对向量进行边界检查。除非您明确检查边界,否则您的程序将会崩溃。如果你想进行边界检查,你需要使用不同的运算符,比如 .at:这会更安全,但也会降低你的软件速度。它归结为优先事项。你要么走得快,要么你改变语法并检查。

因此,如果您更喜欢 self 的 bounds-checking 行为,则需要使用不同的语法编写一个不同的、更安全的访问器。

`%$%` <- function(env, member) {
  member <- deparse(substitute(member))
  ls <- eval(as.call(list(quote(ls), substitute(env))), 
                     envir = parent.frame())
  if(!member %in% ls) stop(member, " is not a member of this R6 class")
  eval(as.call(list(quote(`[[`), substitute(env), member)), 
       envir = parent.frame())
}

x <- R6::R6Class("x", list(foo = function() print(self%$%notexistent),
                           bar = function() print(self%$%baz),
                           baz = 1))
xx <- x$new()

xx$foo()
#> Error in self %$% notexistent : 
#>   notexistent is not a member of this R6 class 

xx$bar()
#> [1] 1

您可能不喜欢不能以这种方式使用 $ 运算符,但这就是 R 的方式。我认为很明显你不喜欢这种语言,我无法改变这一点,但在你摧毁它的计划实现之前,你可以将其视为挑战...