Использование замыкания для генерации привязки R6
Я использую активные привязки в классе 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
1 ответ
Я думаю, вы неправильно понимаете, как работают крышки. 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)
),
)