R: when to use setGeneric or export a s4 method in the namespace

ⅰ亾dé卋堺 提交于 2019-12-23 09:49:29

问题


I am writing a small R package with the idea to submit it to Bioconductor in the future, which is why I decided to try out s4 classes. Unfortunately I had problems understanding when I should use setGeneric or not in my package, and the documentation for the setGeneric method is for me more or less incomprehensible.

Concrete example:

  1. I created a s4 class called Foo
  2. I defined a method for the [<- operator using setMethod("[","Foo", ...)
  3. I defined a method for the as.list function using setMethod("as.list", "Foo",...)
  4. I avoided using setGenerics and exporting my methods in the namespace as I read somewhere that it's not needed for already defined generic functions

The problem now is that the [ accessor method works like a charm, but as.list is not working. Even more confusing, when I import the library BiocGenerics by typing library(BiocGenerics) at the R terminal, as.list starts to work.

Question 1: how can I be sure that [ will always work? And it is not just a coincidence because I imported some libraries?

Question 2: what should I do to make as.list work? Export the method in the namespace? use setGeneric?

Question 3: I thought that as.list started to work because setGeneric("as.list"...) was used in the BiocGenerics package, but this does not seem to be the case, reading from here: http://www.bioconductor.org/packages/release/bioc/manuals/BiocGenerics/man/BiocGenerics.pdf
So why did as.list start to work? Where was it defined?


回答1:


In an R session with only the base packages and methods loaded you can see that the generic for "[" is defined, and the generic for "as.list" is not

> getGeneric("[")
standardGeneric for "[" defined from package "base"

function (x, i, j, ..., drop = TRUE) 
standardGeneric("[", .Primitive("["))
<bytecode: 0x28f7990>
<environment: 0x28ebef0>
Methods may be defined for arguments: x, i, j, drop
Use  showMethods("[")  for currently available ones.
> getGeneric("as.list")
NULL

Loading BiocGenerics does define the generic for as.list

> suppressPackageStartupMessages(library(BiocGenerics))
> getGeneric("as.list")
standardGeneric for "as.list" defined from package "base"

function (x, ...) 
standardGeneric("as.list")
<environment: 0x5969210>
Methods may be defined for arguments: x
Use  showMethods("as.list")  for currently available ones.

If your package is destined for use in Bioconductor, then re-use the generic from BiocGenerics. Do this with the following in your NAMESPACE file

import(methods)
import(BiocGenerics)

exportMethods("[", "as.list")

and with the following in your DESCRIPTION file

Imports: methods, BiocGenerics

If you do not import the generic from BiocGenerics, then your setMethod("as.list", ...) will create it's own generic. In the context of Bioconductor, a user would have to say YourPkg::as.list(YourObject) or BiocGenerics::as.list(NotYourObject) which is clearly not a good idea.

You need to import(methods) because in your interactive trials you're relying on the methods package to be on the search() path. But (a) R CMD BATCH runs without the methods package attached and (b) it is best practice to rely on symbols that are explicitly in your name space, rather than merely on the search path (and hence subject to masking by other packages or user functions with arbitrary behavior. This applies as much to the methods package as any other.



来源:https://stackoverflow.com/questions/28301188/r-when-to-use-setgeneric-or-export-a-s4-method-in-the-namespace

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!