在R中,我想创建一个类(R6Class),当调用initialize时会创建很少的动态方法(方法及其名称的数量取决于初始化中的参数)。但是我遇到了环境问题。
以下是无法使用的简化代码版本。
library(R6)
ffactory <- function(i) {
function() i
}
A <- R6Class(
lock_objects=FALSE,
public=list(
initialize=function(args) {
for (i in args) {
self[[i]] <- ffactory(i)
}
}
)
)
a <- A$new(c('a', 'b', 'c'))
现在:
> a$a()
[1] "c"
> a$b()
[1] "c"
> a$c()
[1] "c"
为了找到错误,我添加了一条在ffactory函数中打印环境的行。那是
ffactory <- function(i) {
print(ls.str())
function() i
}
现在它已经开始工作了!
> a$a()
[1] "a"
> a$b()
[1] "b"
> a$c()
[1] "c"
为什么?应该有一些我不明白的东西。观察者效果还是什么? :)
print(ls.str())
行的神奇之处是什么?实际上我无法从此行中删除print
和str
。当然,拥有这样的线是如此愚蠢。更不用说屏幕上的垃圾了。
答案 0 :(得分:3)
您遇到了延迟评估 - 只要能够在评估i
之前等待R,并且在前一种情况下,i
将在所有实例中的最后一个值进行评估。 print
和ls.str
的组合没有什么特别之处。在方法调用(i
,a$a()
等等...之前强制a$b()
进行评估的任何内容都会做同样的事情。
形式上,这是force
用于:
ffactory <- function(i) {
force(i);
function() i
}
R> a$a()
#[1] "a"
R> a$b()
#[1] "b"
R> a$c()
#[1] "c"
然而,这也恰好做了这个工作:
ffactory <- function(i) {
#force(i);
.z <- capture.output(cat(i, "\n"))
function() i
}
R> a$a()
#[1] "a"
R> a$b()
#[1] "b"
R> a$c()
#[1] "c"
大概有无数种方法可以强制进行评估;我认为使用force
会使你的意图最清楚。
直接引用帮助文件,
强制评估正式论证。这可能很有用 如果参数将通过词法范围捕获在闭包中 规则,稍后将通过明确的转让或改变 循环或应用函数中的隐式赋值。
随后,
这是语义糖:只是评估符号也会这样做 事(见例)。
事实上,看看如何定义force
,
R> force
#function (x)
# x
#<bytecode: 0x3b7b528>
#<environment: namespace:base>
你甚至可以逃脱
ffactory <- function(i) {
i; function() i
}
但如上所述,我认为明确调用force
会使您的代码更具可读性。