【问题标题】:Using a closure to generate an R6 binding使用闭包生成 R6 绑定
【发布时间】:2016-03-02 20:39:52
【问题描述】:

我在 R6 类中使用活动绑定在分配给字段之前检查值。我以为我可以使用闭包来生成如下绑定,但这不起作用。

绑定没有按照我期望的方式进行评估(完全没有?),因为错误显示了闭包的 name 参数。我错过了什么?

library(R6)
library(pryr)

# pass a field name to create its binding 
generate_binding <- function(name) {
  function(value) {
    if (!missing(value) && length(value) > 0) {
      private$name <- value
    } 
    private$name
  }
}

bind_x = generate_binding(x_)
# created as intended:
unenclose(bind_x)
# function (value) 
# {
#     if (!missing(value) && length(value) > 0) {
#         private$x_ <- value
#     }
#     private$x_
# }

MyClass <- R6::R6Class("MyClass",
  private = list(
    x_ = NULL
  ),
  active = list(
    x = bind_x
  ),
)

my_class_instance <- MyClass$new()
my_class_instance$x <- "foo"
# Error in private$name <- value :
#   cannot add bindings to a locked environment

【问题讨论】:

    标签: r r6


    【解决方案1】:

    我认为您误解了闭包的工作原理。 unenclose 在这里是一个红鲱鱼(因为它实际上并没有向您展示关闭的样子)。闭包包含语句private$name &lt;- value——它确实包含语句private$x_ &lt;- value

    这个问题的通常解决方案是重写闭包,以便将未评估的name 参数解析为其字符串表示,然后用于子集private 环境(private[[name]] &lt;- value)。但是,这在此处不起作用,因为 R6 活动绑定会剥离其封闭环境的闭包。

    这就是unenclose 出现的地方:

    MyClass <- R6::R6Class("MyClass",
      private = list(
        x_ = NULL
      ),
      active = list(
        x = pryr::unenclose(bind_x)
      ),
    )
    

    【讨论】:

    • 这太棒了。谢谢。
    猜你喜欢
    • 2020-01-15
    • 2010-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    相关资源
    最近更新 更多