如何为内部泛型的方法添加额外的参数?
How can I add additional arguments to methods for internal generics?
我想为我的 class myClass
实现内部泛型 [<-
(~ help(Extract)
) 的插入方法。
此方法应该 运行 一堆测试,然后通过 NextMethod()
.
将实际的 insetting 关闭到 [<-
我明白了:
- 任何方法都必须至少包含泛型的参数(我认为是我的方法)
NextMethod()
调用通常不需要任何参数(尽管手动提供它们似乎也无济于事)。
这是我的代表:
x <- c(1,2)
class(x) <- c("myClass", "numeric")
`[<-.myClass` <- function(x, i, j, value, foo = TRUE, ...) {
if (foo) {
stop("'foo' must be false!")
}
NextMethod()
}
x[1] <- 3 # this errors out with *expected* error message, so dispatch works
x[1, foo = FALSE] <- 3 # this fails with "incorrect number of subscripts
似乎正在发生的事情是 NextMethod()
也 将 foo
传递给内部泛型 [<-
,这会出错 foo
用于另一个索引,因此会出错(因为在这种情况下,x
没有可作为索引的第二个维度)。
我也尝试明确提供参数 no NextMethod()
,但这也失败了(请参阅中断下方的 reprex)。
我怎样才能避免NextMethod()
因为我的方法的额外参数而窒息?
(奖励:有人知道为内部泛型构建方法的好资源吗?@Hadleys adv-r 在这件事上有点短)。
带有显式参数的 Reprex:
x <- c(1,2)
class(x) <- c("myClass", "numeric")
`[<-.myClass` <- function(x, i = NULL, j = NULL, value, foo = TRUE, ...) {
if (foo) {
stop("'foo' must be false!")
}
NextMethod(generic = "`[<-`", object = x, i = i, j = j, value = value, ...)
}
x[1] <- 3 # this errors out with expected error message, so dispatch works
x[1, foo = FALSE] <- 3 # this fails with "incorrect number of subscripts
这是我的理解,但是我对这方面了解不多,所以我希望我不要说太多错误的话。
来自?NextMethod
NextMethod invokes the next method (determined by the class vector,
either of the object supplied to the generic, or of the first argument
to the function containing NextMethod if a method was invoked
directly).
您的 class 向量是:
x <- c(1,2)
class(x) <- "myClass" # note: you might want class(x) <- c("myClass", class(x))
class(x) # [1] "myClass"
所以你这里没有"next method",[<-.default
也不存在。
如果我们定义它会发生什么?
`[<-.default` <- function(x, i, j, value, ...) {print("default"); value}
x[1, foo = FALSE] <- 3
# [1] "default"
x
# [1] 3
如果有一个带有 ...
参数的默认方法,它会工作得很好,因为 foo
参数会在那里,但事实并非如此,所以我相信 NextMethod
不能被称为原样。
您可以执行以下操作来破解这样一个事实,即无论调用什么都不喜欢被提供 foo
参数:
`[<-.myClass` <- function(x, i, j, value, foo = FALSE, ...) {
if (foo) {
stop("'foo' must be false!")
}
`[<-.myClass` <- function(x, i, j, value, ...) NextMethod()
args <- as.list(match.call())[-1]
args <- args[names(args) %in% c("","x","i","j","value")]
do.call("[<-",args)
}
x[1, foo = FALSE] <- 3
x
# [1] 3 2
# attr(,"class")
# [1] "myClass"
另一个例子,更复杂 class :
library(data.table)
x <- as.data.table(iris[1:2,1:2])
class(x) <- c("myClass",class(x))
x[1, 2, foo = FALSE] <- 9999
# Sepal.Length Sepal.Width
# 1: 5.1 9999
# 2: 4.9 3
class(x)
# [1] "myClass" "data.table" "data.frame"
如果下一个方法有除 x
、i
、j
和 value
以外的其他参数,这将失败,在这种情况下,最好明确说明我们的附加参数参数和 运行 args <- args[! names(args) %in% c("foo","bar")]
。然后它可能会起作用(只要明确给出参数,因为 match.call
不捕获默认参数)。我无法对此进行测试,因为我不知道 [<-
.
的这种方法
除了删除 class(复制 x
)之外,我没有找到解决此问题的简单方法
`[<-.myClass` <- function(x, i, value, ..., foo = TRUE) {
if (foo) {
cat("hi!")
x
} else {
class_x <- class(x)
x <- unclass(x)
x[i] <- value
class(x) <- class_x
x
}
}
x <- structure(1:2, class = "myClass")
x[1] <- 3
#> hi!
x[1, foo = FALSE] <- 3
x
#> [1] 3 2
#> attr(,"class")
#> [1] "myClass"
这不是通用方法 - 只有 [
、[<-
等才需要它,因为它们不使用参数匹配的常规规则:
Note that these operations do not match their index arguments in the standard way: argument names are ignored and positional matching only is used. So m[j = 2, i = 1]
is equivalent to m[2, 1]
and not to m[1, 2]
.
(来自 ?`[`
中的 "Argument matching" 部分)
这意味着您的 x[1, foo = FALSE]
等同于 x[1, FALSE]
然后您会收到一条错误消息,因为 x
不是矩阵。
无效的方法:
向NextMethod()
提供额外的参数:这只会增加参数的数量,而不会减少
取消绑定foo
与rm(foo)
:这会导致关于未定义foo
的错误。
用缺少的符号替换 foo
:这会导致错误,即 foo
未提供默认参数。
我想为我的 class myClass
实现内部泛型 [<-
(~ help(Extract)
) 的插入方法。
此方法应该 运行 一堆测试,然后通过 NextMethod()
.
[<-
我明白了:
- 任何方法都必须至少包含泛型的参数(我认为是我的方法)
NextMethod()
调用通常不需要任何参数(尽管手动提供它们似乎也无济于事)。
这是我的代表:
x <- c(1,2)
class(x) <- c("myClass", "numeric")
`[<-.myClass` <- function(x, i, j, value, foo = TRUE, ...) {
if (foo) {
stop("'foo' must be false!")
}
NextMethod()
}
x[1] <- 3 # this errors out with *expected* error message, so dispatch works
x[1, foo = FALSE] <- 3 # this fails with "incorrect number of subscripts
似乎正在发生的事情是 NextMethod()
也 将 foo
传递给内部泛型 [<-
,这会出错 foo
用于另一个索引,因此会出错(因为在这种情况下,x
没有可作为索引的第二个维度)。
我也尝试明确提供参数 no NextMethod()
,但这也失败了(请参阅中断下方的 reprex)。
我怎样才能避免NextMethod()
因为我的方法的额外参数而窒息?
(奖励:有人知道为内部泛型构建方法的好资源吗?@Hadleys adv-r 在这件事上有点短)。
带有显式参数的 Reprex:
x <- c(1,2)
class(x) <- c("myClass", "numeric")
`[<-.myClass` <- function(x, i = NULL, j = NULL, value, foo = TRUE, ...) {
if (foo) {
stop("'foo' must be false!")
}
NextMethod(generic = "`[<-`", object = x, i = i, j = j, value = value, ...)
}
x[1] <- 3 # this errors out with expected error message, so dispatch works
x[1, foo = FALSE] <- 3 # this fails with "incorrect number of subscripts
这是我的理解,但是我对这方面了解不多,所以我希望我不要说太多错误的话。
来自?NextMethod
NextMethod invokes the next method (determined by the class vector, either of the object supplied to the generic, or of the first argument to the function containing NextMethod if a method was invoked directly).
您的 class 向量是:
x <- c(1,2)
class(x) <- "myClass" # note: you might want class(x) <- c("myClass", class(x))
class(x) # [1] "myClass"
所以你这里没有"next method",[<-.default
也不存在。
如果我们定义它会发生什么?
`[<-.default` <- function(x, i, j, value, ...) {print("default"); value}
x[1, foo = FALSE] <- 3
# [1] "default"
x
# [1] 3
如果有一个带有 ...
参数的默认方法,它会工作得很好,因为 foo
参数会在那里,但事实并非如此,所以我相信 NextMethod
不能被称为原样。
您可以执行以下操作来破解这样一个事实,即无论调用什么都不喜欢被提供 foo
参数:
`[<-.myClass` <- function(x, i, j, value, foo = FALSE, ...) {
if (foo) {
stop("'foo' must be false!")
}
`[<-.myClass` <- function(x, i, j, value, ...) NextMethod()
args <- as.list(match.call())[-1]
args <- args[names(args) %in% c("","x","i","j","value")]
do.call("[<-",args)
}
x[1, foo = FALSE] <- 3
x
# [1] 3 2
# attr(,"class")
# [1] "myClass"
另一个例子,更复杂 class :
library(data.table)
x <- as.data.table(iris[1:2,1:2])
class(x) <- c("myClass",class(x))
x[1, 2, foo = FALSE] <- 9999
# Sepal.Length Sepal.Width
# 1: 5.1 9999
# 2: 4.9 3
class(x)
# [1] "myClass" "data.table" "data.frame"
如果下一个方法有除 x
、i
、j
和 value
以外的其他参数,这将失败,在这种情况下,最好明确说明我们的附加参数参数和 运行 args <- args[! names(args) %in% c("foo","bar")]
。然后它可能会起作用(只要明确给出参数,因为 match.call
不捕获默认参数)。我无法对此进行测试,因为我不知道 [<-
.
除了删除 class(复制 x
)之外,我没有找到解决此问题的简单方法
`[<-.myClass` <- function(x, i, value, ..., foo = TRUE) {
if (foo) {
cat("hi!")
x
} else {
class_x <- class(x)
x <- unclass(x)
x[i] <- value
class(x) <- class_x
x
}
}
x <- structure(1:2, class = "myClass")
x[1] <- 3
#> hi!
x[1, foo = FALSE] <- 3
x
#> [1] 3 2
#> attr(,"class")
#> [1] "myClass"
这不是通用方法 - 只有 [
、[<-
等才需要它,因为它们不使用参数匹配的常规规则:
Note that these operations do not match their index arguments in the standard way: argument names are ignored and positional matching only is used. So
m[j = 2, i = 1]
is equivalent tom[2, 1]
and not tom[1, 2]
.
(来自 ?`[`
中的 "Argument matching" 部分)
这意味着您的 x[1, foo = FALSE]
等同于 x[1, FALSE]
然后您会收到一条错误消息,因为 x
不是矩阵。
无效的方法:
向
NextMethod()
提供额外的参数:这只会增加参数的数量,而不会减少取消绑定
foo
与rm(foo)
:这会导致关于未定义foo
的错误。用缺少的符号替换
foo
:这会导致错误,即foo
未提供默认参数。