代码之家  ›  专栏  ›  技术社区  ›  Anders Ellern Bilgrau

r引用类中的非标准集函数

  •  10
  • Anders Ellern Bilgrau  · 技术社区  · 7 年前

    有可能得到语法吗

    foo$bar(x) <- value
    

    在哪里工作 foo 是引用类对象,并且 bar 是一种方法吗? 也就是说,是否可以在引用类中使用“子集分配”和“替换函数”作为方法?

    语法是否可以与其他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")
    

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

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

    但是,对于在 全名 列表中,我希望有以下语法/接口,这些语法/接口确实失败了。

    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"
    

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

    2 回复  |  直到 7 年前
        1
  •  3
  •   RolandASc    7 年前

    我认为你不能用你想要的语法来完成这个任务。

    请注意,如果运行类似这样的分配,您将得到相同的错误,例如

    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."
    

    我知道这不完全是你想要的,但我希望它有帮助。

        2
  •  3
  •   Adam Waring    7 年前

    我可能误解了你想达到的目标,但这有什么问题?

    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"