我将在下面处理特定情况,但我首先要注意,我们可以生成其他示例,表明当第一个参数为(关于赏金请求)时rbind()
通常没有问题:NextMethod()
...
f <- function(..., b = 3) UseMethod("f")
f.a <- function(..., b = 3) { print("yes"); NextMethod() }
f.integer <- function(..., b = 4) sapply(list(...), "*", b)
x <- 1:10
class(x) <- c("a", class(x))
f(x)
[1] "yes"
[,1]
[1,] 4
[2,] 8
[3,] 12
[4,] 16
[5,] 20
[6,] 24
[7,] 28
[8,] 32
[9,] 36
[10,] 40
f(x, b = 5)
[1] "yes"
[,1]
[1,] 5
[2,] 10
[3,] 15
[4,] 20
[5,] 25
[6,] 30
[7,] 35
[8,] 40
[9,] 45
[10,] 50
那么为什么 rbind.df2 不起作用呢?
事实证明,rbind()
并且cbind()
不是普通的泛型。首先,它们是内部通用的;请参阅 Hadley Wickham 在 Advanced R 上的旧 S3 页面中的“内部泛型”部分,或当前Advanced R的摘录:
一些 S3 泛型,如 [、sum() 和 cbind(),不调用 UseMethod(),因为它们是用 C 实现的。相反,它们调用 C 函数 DispatchGroup() 或 DispatchOrEval()。
这还不足以给我们带来麻烦,正如我们可以看到sum()
的那样:
sum.a <- function(x, na.rm = FALSE) { print("yes"); NextMethod() }
sum(x)
[1] "yes"
[1] 55
然而,rbind
它甚至更奇怪,正如源代码cbind
中的注释中所承认的那样(从第 1025 行开始):
/* cbind(deparse.level, ...) and rbind(deparse.level, ...) : */
/* This is a special .Internal */
...(省略了一些代码)...
/* Lazy evaluation and method dispatch based on argument types are
* fundamentally incompatible notions. The results here are
* ghastly.
在那之后,给出了调度规则的一些解释,但到目前为止我还没有能够使用这些信息来NextMethod()
工作。在上面给出的用例中,我会听从评论中F. Privé的建议并这样做:
new_df2 <- function(x, ...)
{
stopifnot(is.data.frame(x))
structure(x, class = c("df2", "data.frame"))
}
rbind.df2 <- function(..., deparse.level = 1)
{
print("yes") # Or whatever else you want/need to do
base::rbind.data.frame(..., deparse.level = deparse.level)
}
t1 <- data.frame(a = 1:12, b = month.abb)
t2 <- new_df2(t1)
rbind(t2, t2)
[1] "yes"
a b
1 1 Jan
2 2 Feb
3 3 Mar
4 4 Apr
5 5 May
6 6 Jun
7 7 Jul
8 8 Aug
9 9 Sep
10 10 Oct
11 11 Nov
12 12 Dec
13 1 Jan
14 2 Feb
15 3 Mar
16 4 Apr
17 5 May
18 6 Jun
19 7 Jul
20 8 Aug
21 9 Sep
22 10 Oct
23 11 Nov
24 12 Dec