使用set动态构造R6类和实例

时间:2018-08-08 14:40:41

标签: r r6

我想创建一个函数create_thresholds,该函数动态创建R6类和实例对象。这个想法是动态创建一个具有只读活动字段的数据结构,客户端对象可以访问该字段,类似于Wickham所示的示例(https://adv-r.hadley.nz/r6.html-16.3.2活动字段)。我看过dynamically add function to r6 class instance,但我正在寻找一种解决方案,该解决方案可以修改类定义,而不是向实例对象添加函数。

函数create_thresholds读取var / val对的data.frame,然后创建一个R6Class对象,在该对象上尝试设置各种私有字段并创建只读活动字段。该函数通过创建Thresholds对象的新实例来终止。

如下面的代码所示,调用活动方法似乎是在错误的环境中评估方法表达式。

library("R6")


create_thresholds <- function(df) {
  require(glue)
  Thresholds <- R6Class("Thresholds")

    for (i in 1:nrow(df)){
      e <- environment()
      print(e)
      Thresholds$set("private", glue(".{df$var[i]}"), df$val[i])
      Thresholds$set("active", glue("{df$var[i]}"), function() {
        eval(parse(text = glue("private$.{df$var[i]}")))
      })
    }

  th <- Thresholds$new()

  return(th)
}

df <- tibble::tribble(~var, ~val,
                      "min_units", 100,
                      "min_discount", 999)


th <- create_thresholds(df)
th$min_discount ## expect 999
th$min_units ## OOPS! expect 100

1 个答案:

答案 0 :(得分:0)

以下解决方案需要动态创建整个函数/方法定义的字符串形式,然后在其上调用eval(parse())

library("R6")


df <- tibble::tribble(~var, ~val,
                      "min_units", 100,
                      "min_discount", 999)

create_thresholds <- function(df) {
  Thresholds <- R6Class("Thresholds")

  for (i in 1:nrow(df)){
    mthd_name <- df$var[i]
    mthd_def <- glue::glue("function() private$.{mthd_name}")
    Thresholds$set("private", glue(".{mthd_name}"), df$val[i])
    Thresholds$set("active", mthd_name, eval(parse(text = mthd_def)))
  }

  hh <- Thresholds$new()
  return(hh)
}

hh <- create_thresholds(df)
hh$min_discount # expect 999!
hh$min_units #expect 100