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

Ste*_*ini -4 r r6

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

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

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

All*_*ron 5

self在R6功能的环境。在$对环境的运营商是一种原始的,而据我可以告诉它不能被覆盖。默认情况下,NULL如果在环境中找不到右侧操作数,则此运算符将返回而不是抛出错误,并且该事实必须由调用者显式处理。

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

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

`%$%` <- 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
Run Code Online (Sandbox Code Playgroud)

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