在R6Class中创建动态方法,打印魔术(ls.str())

时间:2015-12-08 23:32:06

标签: r r6

在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())行的神奇之处是什么?实际上我无法从此行中删除printstr。当然,拥有这样的线是如此愚蠢。更不用说屏幕上的垃圾了。

1 个答案:

答案 0 :(得分:3)

您遇到了延迟评估 - 只要能够在评估i之前等待R,并且在前一种情况下,i将在所有实例中的最后一个值进行评估。 printls.str的组合没有什么特别之处。在方法调用(ia$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会使您的代码更具可读性。