为什么`预测'不是通用函数?

时间:2014-01-17 07:43:34

标签: r

为什么predict不是通用函数? isGeneric('predict')FALSE,但isGeneric('summary')isGeneric('print')TRUE。他们都有方法,可以列出methods('predict')等?因此predict不是here描述的通用函数(从class看也很明显),但仍会根据传递给它的对象调度方法(例如predict.lm或{ {1}})。那么R调度方法有不同的方式吗?如何测试函数是否具有方法,以便上述所有示例都为真?是的,我可以测试predict.glm的长度,但是对没有方法的函数会产生警告。

2 个答案:

答案 0 :(得分:15)

首先,你的测试中没有一个是通用的:

> isGeneric('predict')
[1] FALSE
> isGeneric('summary')
[1] FALSE
> isGeneric('print')
[1] FALSE

让我们再试一次......

> isGeneric("summary")
[1] FALSE
> require(sp)
Loading required package: sp
> isGeneric("summary")
[1] TRUE

这里发生了什么?好吧,isGeneric只测试S4泛型函数,当我启动R summary时是一个S3泛型函数。如果一个包想要使用S4方法和类,并且已经存在S3泛型函数,那么它可以创建一个S4泛型。

所以,最初summary是:

> summary
function (object, ...) 
UseMethod("summary")
<bytecode: 0x9e4fc08>
<environment: namespace:base>

这是一个S3泛型。我得到了sp包......

> require(sp)
Loading required package: sp
> summary
standardGeneric for "summary" defined from package "base"

function (object, ...) 
standardGeneric("summary")
<environment: 0x9f9d428>
Methods may be defined for arguments: object
Use  showMethods("summary")  for currently available ones.

现在summary是S4标准通用。

S3泛型方法通常通过调用{generic}.{class}来发送,这是UseMethod("summary")在S3 summary泛型函数中的作用。

如果要测试函数是否具有特定类的方法,那么您可能必须测试它是否具有S4方法(使用S4方法元数据的函数)和S3方法(通过查找名为{generic}.{class},例如summary.glm

太棒了?

答案 1 :(得分:2)

我对S3泛型的一般理解来自from the R Language manual,我在其中认为函数func在不调用UseMethod的情况下不能成为泛型。因此,如果没有任何精美的软件包,您可以使用以下gist

isFuncS3Generic <- function(func) {
  funcBody <- body(func)
  sum(grepl(pattern="UseMethod", x=funcBody)) != 0
}

编辑:使用石蕊测试:

> isFuncS3Generic(print)
[1] TRUE
> isFuncS3Generic(predict)
[1] TRUE
> isFuncS3Generic(summary)
[1] TRUE
> isFuncS3Generic(glm)
[1] FALSE
@Hadley,我不确定为什么这是一个难题。你介意详细说明吗?