使用闭包生成 R6 绑定
Using a closure to generate an R6 binding
我在 R6 class 中使用活动绑定在分配给字段之前检查值。我以为我可以使用闭包来生成如下绑定,但这不起作用。
绑定未按我预期的方式(完全没有?)进行评估,因为错误显示了闭包的 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
我认为你误解了闭包的工作原理。 unenclose
在这里是一个转移注意力的问题(因为它实际上并没有向您展示闭包的样子)。闭包包含语句 private$name <- value
— 它 不 包含语句 private$x_ <- value
.
此问题的通常解决方案是重写闭包,以便将未评估的 name
参数分解为其字符串表示形式,然后用于子集 private
环境(private[[name]] <- value
).但是,这在这里不起作用,因为 R6 活动绑定剥离了封闭环境的闭包。
这就是 unenclose
的用武之地:
MyClass <- R6::R6Class("MyClass",
private = list(
x_ = NULL
),
active = list(
x = pryr::unenclose(bind_x)
),
)
我在 R6 class 中使用活动绑定在分配给字段之前检查值。我以为我可以使用闭包来生成如下绑定,但这不起作用。
绑定未按我预期的方式(完全没有?)进行评估,因为错误显示了闭包的 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
我认为你误解了闭包的工作原理。 unenclose
在这里是一个转移注意力的问题(因为它实际上并没有向您展示闭包的样子)。闭包包含语句 private$name <- value
— 它 不 包含语句 private$x_ <- value
.
此问题的通常解决方案是重写闭包,以便将未评估的 name
参数分解为其字符串表示形式,然后用于子集 private
环境(private[[name]] <- value
).但是,这在这里不起作用,因为 R6 活动绑定剥离了封闭环境的闭包。
这就是 unenclose
的用武之地:
MyClass <- R6::R6Class("MyClass",
private = list(
x_ = NULL
),
active = list(
x = pryr::unenclose(bind_x)
),
)