R语言中的'as'函数的类型/来源是什么?

8
R的S3 OO系统是围绕着通用函数展开的,这些函数根据调用它们的对象的类别来调用方法。关键在于通用函数调用适当的方法,而不是在类中定义方法,这与其他面向对象编程语言不同。
例如,`mean`函数是一个通用函数。
isGeneric("mean")
methods(mean)

这将会打印出来

TRUE
[1] mean,ANY-method          mean.Date                mean.default             mean.difftime           
[5] mean.IDate*              mean,Matrix-method       mean.POSIXct             mean.POSIXlt            
[9] mean,sparseMatrix-method mean,sparseVector-method
see '?methods' for accessing help and source code

我在探索R语言时发现了as函数。但是我对于R声称该函数不是通用函数,却仍然有方法感到困惑。

isGeneric("as")
methods(as)

TRUE
  [1] as.AAbin                                  as.AAbin.character                       
  [3] as.alignment                              as.allPerms                              
  [5] as.array                                  as.array.default                         
  [7] as.binary                                 as.bitsplits                             
  [9] as.bitsplits.prop.part                    as.call
  ...                                  

在最后,有一个警告提示说as不是通用的。
 Warning message:
 In .S3methods(generic.function, class, parent.frame()) :
 function 'as' appears not to be S3 generic; found functions that look like S3 methods

有人能解释一下 as 函数是什么,以及它与 as.listas.data.frame 等的关系吗?R 说 as.list 是一个通用函数(我对 R 中的不一致性感到有点生气,因为我本来希望 as.list 是从 as 通用函数中针对 list 对象的方法)。请帮忙。


1
?as,列出的S3函数是那些像方法命名的函数,但实际上可能并不是方法(已知的例外在代码中被丢弃)。如果您查看as的源代码,它看起来不像一个只有UseMethod调用的S3通用函数(如mean),这加强了它不是通用函数的说法。然而,这只是故事的一部分;这里肯定还有更多的内容需要讲述。 - alistaire
1
糟糕,上述引用是来自?methods,而不是?as - alistaire
1个回答

11
as不是S3通用函数,但请注意,您得到了一个TRUE。(我得到了一个FALSE。)这意味着您加载了一个定义 as 为S4通用函数的包。 S3通用函数通过类分派工作,使用 *.default 函数和 UseMethod 函数。我得到的 FALSE 表示没有为要查找的通用函数 as 定义方法。缺乏通用函数 as 的一个可争议的原因是,仅使用一个数据对象调用此类函数将不指定“强制转换目标”。这意味着目标需要构建到函数名称中。

在将 as 声明为通用函数之后(请注意大写字母表明这适用于S4功能:

setGeneric("as")  # note that I didn't really even need to define any methods

get('as')
#--- output----
standardGeneric for "as" defined from package "methods"

function (object, Class, strict = TRUE, ext = possibleExtends(thisClass, 
    Class)) 
standardGeneric("as")
<environment: 0x7fb1ba501740>
Methods may be defined for arguments: object, Class, strict, ext
Use  showMethods("as")  for currently available ones.

如果我重新启动R(不加载任何调用“as”函数的库),我会得到以下结果:
get('as')
#--- output ---
function (object, Class, strict = TRUE, ext = possibleExtends(thisClass, 
    Class)) 
{
    if (.identC(Class, "double")) 
        Class <- "numeric"
    thisClass <- .class1(object)
    if (.identC(thisClass, Class) || .identC(Class, "ANY")) 
        return(object)
    where <- .classEnv(thisClass, mustFind = FALSE)
    coerceFun <- getGeneric("coerce", where = where)
    coerceMethods <- .getMethodsTable(coerceFun, environment(coerceFun), 
        inherited = TRUE)
    asMethod <- .quickCoerceSelect(thisClass, Class, coerceFun, 
        coerceMethods, where)
    .... trimmed the rest of the code

但你问“为什么”,这当然是在讨论语言设计时一个危险的问题。我翻阅了《S中的统计模型》的最后一章,这本书是大多数适用于S3分发的帮助页面的引用参考文献,并没有讨论强制转换或as函数的任何内容。虽然有一个隐含的“S3通用”定义,需要使用UseMethod,但其中没有提到为什么将as排除在该策略之外。我想到了两个可能性:这是为了防止强制转换的应用中出现任何继承歧义,或者这是出于效率考虑。
我还应该补充一点,就是S4有一个setAs函数,你可以用showMethods("coerce")找到所有的S4 coercion函数。

这里仍有一个未解决的问题,即为什么像as.character这样的强制转换函数被命名为as的S3方法,即使它们并不是(因为它们的结构)。我相信这是“历史原因”,但我很好奇R最终如何出现如此明显的不一致性。 - alistaire
3
我提出了我的理论,但我认为这实际上是一个“向作者提问”的问题,而很少有作者会经常访问Stack Overflow。也许在Rhelp上发出查询会更加有益。 - IRTFM

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接