微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

R 如何找到 S3 方法?为什么 R 找不到我的 S3 `+` 方法?

如何解决R 如何找到 S3 方法?为什么 R 找不到我的 S3 `+` 方法?

我想创建并attach一个包含 S3 方法environment 并让 R 在搜索路径中找到它们,使用方法名称(即,我应该能够使 infix-style a + b 工作,而不必编写 prefix-style "+.Foo"(a,b))。我究竟做错了什么?虽然相当长,但我可以在合理的时间内提出的最短示例如下。评论详细说明了情况和问题。

更新:我为每个选定的答案附加了更多代码

# **** CLEAR THE USER WORKSPACE / GLOBAL ENVIRONMENT ****
rm(list = ls( all = TRUE ))

# **** RESET THE SEARCH PATH. (I'VE NEVER HAD AN R INSTALLATION THAT DOESN'T BOOT ****
# **** WITH package:stats AS THE SECOND-TO-LAST ITEM ON THE SEARCH PATH.)                   ****
while (search()[[2]] != "package:stats") detach()

search ()
# [1] ".GlobalEnv" "package:stats" "package:graphics" "package:Grdevices" "package:utils"
# [6] "package:datasets" "package:methods" "Autoloads" "package:base"     

x <- 1L
class (x) <- "Foo"

`+.Foo` <- function ( x,y ) {
    cat("This is `x.Foo`\n")
    # "non-standard" addition on purpose
    z <- -1L * ( as.integer(x) + as.integer(y) )
    class(z) <- "Foo"
    z }

x + x
# This is `x.Foo`
# [1] -2
# attr(,"class")
# [1] "Foo"

# Note that R finds `x.Foo` in the global environment.

FooEnv <- new.env(parent = as.environment(search()[[2]]))
attr(FooEnv,"name") <- "FooEnv"
FooEnv
# <environment: 0xhhhhhhhhhhhhhhhh> ## Each h is a hex-digit.
# attr(,"name")
# [1] "FooEnv"

parent.env(FooEnv)
# <environment: package:stats>
# attr(,"name")
# [1] "package:stats"
# attr(,"path")
# [1] "C:/Program Files/R/R-4.0.3/library/stats"

# The path above will vary with the R installation.

# I want the next 3 lines of R code is to replace `+.Foo` in the global environment
# with `x.Foo` on the search path.
FooEnv $ `+.Foo` <- `+.Foo`
rm(`+.Foo`)
attach(what = FooEnv,name = attr(FooEnv,"name"))

search()
# [1] ".GlobalEnv" "FooEnv" "package:stats" "package:graphics" "package:Grdevices"
# [6] "package:utils" "package:datasets" "package:methods" "Autoloads" "package:base"    

x + x
# [1] 2
# attr(,"class")
# [1] "Foo"

## Note lack of "This is `x.Foo`".
## Note the sign.
## This is not the `+` we're looking for.

# `methods` finds `+.Foo`:
methods("+")
# [1] +.Date +.Foo +.POSIXt
# see '?methods' for accessing help and source code

# `find` finds `+.Foo`
find("+.Foo")
# [1] "FooEnv"

# Although the following works,I want to call `x.Foo` using infix style.
`+.Foo`(x,x)
# This is `x.Foo`
# [1] -2
# attr(,"class")
# [1] "Foo"

write.dcf(R.Version())
# platform: x86_64-w64-mingw32
# arch: x86_64
# os: mingw32
# system: x86_64,mingw32
# status:
# major: 4
# minor: 0.3
# year: 2020
# month: 10
# day: 10
# svn rev: 79318
# language: R
# version.string: R version 4.0.3 (2020-10-10)
# nickname: Bunny-Wunnies Freak Out

# `.S3method` seems to do the trick. AckNowledgement: @MrFlick
.S3method("+","Foo")
x + x
# This is `x.Foo`
# [1] -2
# attr(,"class")
# [1] "Foo"

解决方法

如果您没有将 S3 方法注册为包命名空间的一部分或在全局环境中,则需要使用 .S3method() 函数显式注册它。所以在这种情况下你会做

.S3method("+","Foo",FooEnv$`+.Foo`)

这里进一步讨论了这个问题:https://developer.r-project.org/Blog/public/2019/08/19/s3-method-lookup/

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。