何时使用响应式表达式与使用 <<- 创建全局对象

When to use a reactive expression vs to use <<- to create a global object

我正在尝试使用我的同事创建的一些功能来创建一个 Shiny 应用程序。他经常在他的函数中使用“<<-”运算符来创建全局对象。

问题: 1. 在这种情况下使用 <<- 是一种好习惯吗? 2. 如果我使用 reactive() 来表示对象,应用程序会更快吗? 3.有更好的建议吗?

下面是他写的函数的例子:

PrepareData<-function(pickoneperday=TRUE,data) { 
  set.seed(1)
  if (pickoneperday==TRUE) {data <<- PickOnePerDay(data)} 
  data <<- RankData(data)
  SetMeasureType()
  minnodebase <<- 0.005*nrow(data)
  CodeMissingData(data)
}

首先,我认为我们需要明确问题的范围。

  1. 如果您在 R 中编写函数,为了清楚起见,最好在函数末尾使用 return() 来 return 值,或者至少将数据对象放在最后大括号。在这种情况下,使用 <<- 会产生任何类型的错误和并发症(简而言之,这是意大利面条式编程的提醒,打破了有问题的函数只有一个出口点的规则)。
  2. 不同的是shiny特殊函数的情况。我只是想提醒一下,shiny 编码人员通常不会在 shiny 函数的末尾使用 return()(即使它仍然有效)。这里要么没有值 returned,要么使用了 reactive 或其他类似的结构。

部分混淆来自问题中的最小示例:该示例不是 shiny 特殊函数,而只是一个普通函数。

shiny中,使用例如observe这样的构造,可能碰巧使用<<-来更新全局对象。一个很好的例子(我经常回顾的一段很棒的代码)是由闪亮的开发人员之一 Jeff Allen 开发的应用程序 ShinyChat - see here on github。 在这种情况下,Jeff 使用 <<-observe 函数中更新在全局级别定义的 reactiveValue:非常好的风格。

我总结一个小问题:如果你有任何函数并且你用 <<- 更新了一个变量,并且你有一个在本地定义的同名变量,那么只有全局变量会被更新。 在这些情况下,您需要执行类似

的操作
data <<- data <- 3

从右到左:第一个 <- 更新了名为 data 的局部变量:第二个 <<- 更新了名为 data 的全局变量。说说迷惑。

另一方面,在 shiny 或标准 R 中,我从来没有注意到因为 <<- 而导致的严重缓慢,当然前提是代码中没有太多。

关于 reactivereactiveValues 等替代技术的问题,请参阅 SO 上对类似问题 的这个很好的回答。