【问题标题】:Non-standard set-functions in R Reference ClassesR 参考类中的非标准集合函数
【发布时间】:2019-01-15 20:56:14
【问题描述】:

是否可以获取语法

foo$bar(x) <- value

foo 是引用类对象且bar 是方法的情况下工作? IE。是否可以在引用类中进行“子集分配”并具有“替换函数”作为方法?

其他 OO 系统可以使用该语法吗?

示例: 我将用一个虚构的用例来说明。想象一个参考类Person,其中包含一个人的一些基本信息。特别是,一个名为fullname 的字段是一个名为list

PersonRCGen <- setRefClass("Person",
                           fields = list(
                             fullname = "list",
                             gender = "character"
                           ))

接下来,我们应该定义一些方法来获取和设置fullnames 列表中的特定名称(尝试)以提供上述语法/接口。到目前为止,我最好的尝试是:

PersonRCGen$methods(
  name = function(x) { # x is the dataset,
    .self$fullname[[x]]
  },
  `name<-` = function(x, value) {
    .self$fullname[[x]] <- value
  }
)

这里的命名也应该说明我想要做什么。

我们初始化一个新对象:

a_person <- PersonRCGen$new(fullname = list(first = "Jane", last = "Doe"),
                            gender = "F")

直接访问 fullname 字段并通过定义的 get 函数访问名字和姓氏按预期工作:

a_person$fullname
#$`first`
#[1] "Jane"
# 
#$last
#[1] "Doe"

a_person$name("first")
#[1] "Jane"

a_person$name("last")
#[1] "Doe"

但是,为了在 fullname 列表中设置特定名称,我希望使用以下语法/接口,但不幸的是失败了。

a_person$name("first") <- "Jessie"
#Error in a_person$name("first") <- "Jessie" : 
#  target of assignment expands to non-language object

我知道以下作品(基本上使该方法命名不佳)。

a_person$`name<-`("first", "Johnny")
a_person$fullname
#$`first`
#[1] "Johnny"
#
#$last
#[1] "Doe"

在我的实际用例中,我想避免 get 和 set 函数使用“传统”getName(x)setName(x, value) 名称。

【问题讨论】:

  • 我认为此类功能的“特定名称”将是“分配”。您还应该意识到$&lt;-[[&lt;- 的同义词,尽管您的代码表明您可能已经理解了这一点。
  • @42- 是的,但赋值通常指的是assign-函数或&lt;-,当然这也是一个函数。至于$&lt;-[[&lt;-,我想说这些是子集上下文中“赋值函数”的例子。我更想为所有承认foo(x) &lt;- value 语法的'foo&lt;-'(x, value) 函数命名。因此,如果您愿意,我会为这种类型的函数寻找一个 more 特定名称(如果存在)。换句话说,我如何用谷歌搜索它?
  • 我认为搜索文档文件更有可能返回可管理的点击数。
  • @42- 谢谢。我再次尝试(按照您的建议遵循[[&lt;- 的文档),这导致了我herehere。所以名称似乎是“替换函数”或“子集分配”。
  • 因此,“命名分配”或“按字符索引分配”或“子分配”可能会在比 Rhelp 或 R-devel 更熟悉参考类函数的人身上触发适当的神经元集我是吗?

标签: r reference-class


【解决方案1】:

我认为你不能用你想要的语法来做到这一点。

请注意,如果您运行任何类似的作业,您将得到相同的错误,例如

a_person$hello("first") <- "John"

所以这确实是一个基本问题。

起作用的是以下语法:

name(a_person, "first") <- "John"

总之你可以有如下的东西:

PersonRCGen <- setRefClass("Person",
                  fields = list(
                    fullname = "list",
                    gender = "character"
                  ),
                  methods = list(
                    initialize = function(...) {
                      initFields(...)
                    },
                    name = function(x) {
                      .self$fullname[[x]]
                    }
                  )
)

setGeneric("name<-", function(x, y, value) standardGeneric("name<-"))
setMethod("name<-", sig = "ANY", function(x, y, value) {
  UseMethod("name<-")
})
# some extras
"name<-.default" <- function(x, y, value) {
  stop(paste("name assignment (name<-) method not defined for class", class(x)))
}
"name<-.list" <- function(x, y, value) {
  x[[y]] <- value
  return(x)
}
# and here specifically
"name<-.Person" <- function(x, y, value) {
  x$fullname[[y]] <- value
  return(x)
}

# example to make use of the above
a_person <- PersonRCGen$new(
  fullname = list(
    first = "Jane",
    last = "Doe"
  ),
  gender = "F"
)

a_person$name("first")
#> [1] "Jane"
name(a_person, "middle") <- "X."
a_person$name("middle")
#> [1] "X."

我知道这不是您想要的,但我希望它有所帮助。

【讨论】:

  • 感谢您的回答。虽然我仍然不明白为什么它不起作用,但我开始接受它确实是不可能的。我绝对喜欢您对替代语法的建议。但也许我只需要一个标准的参考类分配函数——我不确定我是否要将 S3 系统带入其中并增加另一层复杂性。这用的是S3系统吧?无论如何,如果没有其他答案更接近我想要的语法,我会奖励你答案。
  • 正确,这最终是使用 S3。请注意,setGenericsetMethod 通常会首先在 S4 的上下文中弹出。
【解决方案2】:

我可能误解了您想要实现的目标,但这有什么问题?

person = setRefClass("Person",
                     fields = list(
                       fullname = "list",
                       gender = "character"
                     ))

a_person = person$new(fullname = list(first = "James", last = "Brown"), gender="M")

a_person$fullname$first = "Bob"

a_person

Reference class object of class "Person"
Field "fullname":
$`first`
[1] "Bob"

$last
[1] "Brown"

Field "gender":
[1] "M"

【讨论】:

  • 嗯,它本身并没有什么问题。但我正在工作的项目更喜欢获取和设置函数,而不是直接操作字段。其次,用例并不像上面的那么简单。这些字段是更复杂的数据结构,需要做一些“特殊”的事情。最后,我发现赋值函数 (myfunction(x) &lt;- value) 比 RC 中的常规集合函数 (myfunction(x, value)) 更适合 R。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-02-17
  • 1970-01-01
  • 1970-01-01
  • 2018-05-11
  • 2019-11-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多