将非 S3 基本函数重新定义为 R 包中的 S3 函数是不好的风格吗?
Posted
技术标签:
【中文标题】将非 S3 基本函数重新定义为 R 包中的 S3 函数是不好的风格吗?【英文标题】:Is it bad style to redefine non-S3 base functions as S3 functions in an R package? 【发布时间】:2017-02-14 20:58:58 【问题描述】:所以我正在开发一个使用 S3 类的 R 包,如果我可以使用 sample
作为我的一个类的方法,那就太好了。但是,base
已经将sample
声明为非 S3 函数,所以我想知道的是:
将非 S3 base
函数(例如 sample
)重新定义为 S3 函数是不是很糟糕?这会给我的软件包的用户带来麻烦吗?
您可以重新定义 sample
并保持 base
函数正常工作的方法是:
sample.default <- base::sample
sample <- function(x, ...)
UseMethod("sample")
# This allows me to define a new sample method for my_special_class
sample.my_special_class <- function(...) ...
但我不确定这是否会导致任何麻烦或命名空间问题,例如,在加载其他包时。我也注意到没有多少包重新定义sample
,例如,dplyr 使用sample_n
,igraph 使用sample_
,我认为这可能有一些原因......
【问题讨论】:
如果您还没有,也许您可以创建自己的类并定义一个sample.yourclassname
来处理您的类。通过这种方式,您可以保持使用泛型函数的一致性。
@RomanLuštrik:这行不通,因为base::sample
不是通用的。如果它是通用的,则没有理由在您的包中重新定义它;你只需注册你的方法。
@JoshuaUlrich bah,你打败了我。刚刚在您发帖前几秒钟检查了功能。你是对的。回到绘图板。
见***.com/questions/41884629/…
【参考方案1】:
“风格”是否糟糕主要取决于意见。但是编写 R 扩展,Section 7.1 - Adding new generics 告诉您如何添加新的泛型来屏蔽基本的基本/推荐功能。也就是说,该部分明确警告您提出的解决方案:
...一个包可以接管基础包中的一个功能,并通过类似的方式使其通用
foo <- function(object, ...) UseMethod("foo") foo.default <- function(object, ...) base::foo(object)
本手册的早期版本建议分配
foo.default <- base::foo
。这不是一个好主意,因为它会在安装时捕获基本功能,并且可能会随着 R 的修补或更新而更改。
其他人可能遇到的一个问题是,如果另一个包也将summary
注册为泛型。然后根据您的包或其他包的包需要决定向哪个泛型注册他们的方法。
没有多少包重新定义sample
,因为屏蔽基本/推荐函数通常不是一个好主意。这使用户有可能在顶层获得不同的行为,具体取决于您的包是否已加载。
您肯定要避免的一件事是在基本/推荐(或高度使用)包中屏蔽泛型。这样做可以防止在顶层进行方法分派,从而让期望泛型工作的用户感到头疼(例如dplyr::lag
)。
【讨论】:
如果我对手册的理解正确,CRAN 建议您定义sample.default <- function(x, ...) base::sample(x, ...)
并认为这是允许的。
@Benjamin 为什么不创建自己的类并扩展泛型来处理该类?
@RomanLuštrik 根据大数定律,它最终必须发生。 :)
@Benjamin 我的人生策略。
@RasmusBååth:我提到这是一个可能的问题,但可能性很小。包需要使用 both 包来创建通用并且想要注册sample
方法。以上是关于将非 S3 基本函数重新定义为 R 包中的 S3 函数是不好的风格吗?的主要内容,如果未能解决你的问题,请参考以下文章