4

根据我阅读Hadley 关于构建 S3 对象的建议,我正在使用辅助函数、构造函数和验证器函数。一个简单的可重现示例:

test_object <- function(x, y, z) {
    new_test_object(x, y, z)
}

new_test_object <- function(x, y, z) {
    structure(list(x = x,
                   y = y,
                   z = z,
                   x_name = deparse(substitute(x))),
              class = "test_object")
}

validate_test_object <- function(test_object) {
    # Anything goes
    test_object
}

我希望生成的对象包含一个带有传入项目的原始名称的值($x_name在上面的示例中)。如果我直接调用构造函数,这个deparse(substitute(...))技巧就有效:

alpha = "a"
test_constructor <- new_test_object(x = alpha, y = "b", z = "c")
test_constructor$x_name
# [1] "alpha"

但如果我使用辅助函数则不是:

test_helper <- test_object(x = alpha, y = "b", z = "c")
test_helper$x_name
# [1] "x"

我也想test_helper$x_name退货[1] "alpha"

如果没有在帮助器阶段执行该deparse(substitute(...))步骤,构造函数 ( )是否可以通过帮助器new_test_object()访问对象的“原始”名称?x或者确保它的名称随着辅助函数传递给构造函数而传递?

4

2 回答 2

5

这里的真正目的是什么?如果您只是将一个函数用作另一个函数的包装器,那么有更好的方法来保存参数。例如

test_object <- function(x, y, z) {
  call <- match.call()
  call[[1]]  <- quote(new_test_object)
  eval(call)
}

但总的来说,依靠deparse()从变量名称中获取信息并不是一种非常可靠的方法。如果您愿意,最好让这些信息成为您可以设置的适当参数。这使您的功能更加灵活。

test_object <- function(x, y, z, xname=deparse(substitute(x))) {
    new_test_object(x, y, z, xname=xname)
}

new_test_object <- function(x, y, z, xname=deparse(substitute(x))) {
    structure(list(x = x,
                   y = y,
                   z = z,
                   x_name = xname),
              class = "test_object")
}
于 2017-09-08T15:44:02.937 回答
0

这是一个不漂亮的修复:...当您从另一个函数调用它时,添加参数以传递名称

test_object <- function(x, y, z) {
  x_name = deparse(substitute(x))
  new_test_object(x, y, z, x_name = x_name)
}

new_test_object <- function(x, y, z, ...) {
  args <- list(...)
  if(is.null(args[["x_name"]])){
    structure(list(x = x,
                   y = y,
                   z = z,
                   x_name = deparse(substitute(x))),
              class = "test_object")
  }
  else{
    structure(list(x = x,
                   y = y,
                   z = z,
                   x_name = args[["x_name"]]),
              class = "test_object")
  }

}

结果如下:

test_helper <- test_object(x = alpha, y = "b", z = "c")
test_helper$x_name
# [1] "alpha"
于 2017-09-08T15:43:24.457 回答