首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在闪亮的上下文之外创建一个反应性的、可回忆性的功能

在闪亮的上下文之外创建一个反应性的、可回忆性的功能
EN

Stack Overflow用户
提问于 2019-01-23 10:40:42
回答 1查看 287关注 0票数 0

我试图通过利用来自shiny的函数来创建一个现有函数的“反应式和回忆性”版本--但是用于在一个闪亮的上下文之外使用。

依赖shiny::reactive()最酷的一点是

  1. 它“自动地”知道它的反应性依赖关系。
  2. 它为我们处理“返回缓存或重新执行底层快速处理”的决定。

虽然我将函数的body (而不是函数本身的)传递给shiny::reactive()的方法本身是有效的,但它让我放弃了只对missing()match.arg()这样的函数起作用的东西。

但是,我似乎无法找到一种将函数本身交给shiny::reactive()的方法,同时仍然利用其内置的缓存/回忆录。要了解这一点,请注意,每次调用foo()时,实际上都会执行foo_react(),因此在第二种方法中不使用缓存。

方法1

代码语言:javascript
复制
# Preliminaries -----
library(shiny)
library(rlang)
options(shiny.suppressMissingContextError=TRUE)
shiny:::setAutoflush(TRUE)

makeReactiveBinding("x_react")
makeReactiveBinding("foo")

# Approach 1: hand foo()'s body to reactive() ----
foo <- function(x_react = get("x_react", 1)) {
  message("Executing foo()")
  x_react * 10
}

expr_inner <- quo(!!fn_body(foo))
expr_react <- quo(reactive({!!expr_inner}))
foo_react <- eval_tidy(expr_react)
print(foo_react)
#> reactive({
#>     ~{
#>         message("Executing foo()")
#>         x_react * 10
#>     }
#> })

x_react <- 1
foo_react() # Executes body of foo()
#> Executing foo()
#> [1] 10
foo_react() # Uses cached result
#> [1] 10
x_react <- 10
foo_react() # Executes body of foo()
#> Executing foo()
#> [1] 100
foo_react() # Uses cached result
#> [1] 100

reprex封装创建于2019年-01-23 (v0.2.1)

方法2

代码语言:javascript
复制
# Approach 2: handing foo() itself to reactive() -----
expr_inner <- quo(!!foo)
expr_react <- quo(shiny::reactive({!!expr_inner}))
foo_react <- eval_tidy(expr_react)
print(foo_react)
#> reactive({
#>     ~function (x_react = get("x_react", 1)) 
#>     {
#>         message("Executing foo()")
#>         x_react * 10
#>     }
#> })

x_react <- 1
foo_react()() # Executes foo()
#> Executing foo()
#> [1] 10
foo_react()() # Does NOT use cached result, but executes foo() again
#> Executing foo()
#> [1] 10
x_react <- 10
foo_react()() # Executes foo()
#> Executing foo()
#> [1] 100
foo_react()() # Does NOT use cached result, but executes foo() again
#> Executing foo()
#> [1] 100

reprex封装创建于2019年-01-23 (v0.2.1)

请注意,当将foo()的主体交给reactive()时,我们将失去使用missing()match.arg()之类的东西的能力。

代码语言:javascript
复制
foo <- function(x_react = get("x_react", 1), y = c("a", "b")) {
  message("Executing foo()")
  try(print(missing(x)))
  try(print(match.arg(y)))
  x_react * 10
}

# Approach 1 -----
expr_inner <- quo(!!fn_body(foo))
expr_react <- quo(reactive({!!expr_inner}))
foo_react <- eval_tidy(expr_react)

x_react <- 1
foo_react() # Executes body of foo()
#> Executing foo()
#> [1] 10

# Approach 2 -----
expr_inner <- quo(!!foo)
expr_react <- quo(shiny::reactive({!!expr_inner}))
foo_react <- eval_tidy(expr_react)

x_react <- 1
foo_react()() # Executes foo()
#> Executing foo()
#> [1] TRUE
#> [1] "a"
#> [1] 10

reprex封装创建于2019年-01-23 (v0.2.1)

奇怪的是,在方法1中尝试使用missing()match.arg()不会在通过reprex::reprex()运行代码时导致错误,但在交互模式下会导致错误。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-01-24 02:59:45

抱歉,我不太理解rlang的东西。但是,您是否可以在一个反应表达式中调用foo()函数,如果需要的话,将它封装在一个函数中以传递args?我尝试过像这样调整方法2:

代码语言:javascript
复制
library(shiny)
library(rlang)
options(shiny.suppressMissingContextError=TRUE)
shiny:::setAutoflush(TRUE)

makeReactiveBinding("x_react")
makeReactiveBinding("foo")

foo <- function(x_react = get("x_react", 1), y = c("a", "b")) {
  message("Executing foo()")
  try(print(missing(x_react)))
  try(print(match.arg(y)))
  x_react * 10
}

foo_react <- function(...) {
  reactive({
    foo(...)
  })
}

## no args
f <- foo_react()
x_react <- 1
f()
# Executing foo()
# [1] TRUE
# [1] "a"
# [1] 10
f()
# [1] 10

x_react <- 10
f()
# Executing foo()
# [1] TRUE
# [1] "a"
# [1] 100
f()
# [1] 100

## with args
f <- foo_react(x_react = 3, y = "b")
f()
# Executing foo()
# [1] FALSE
# [1] "b"
# [1] 30
f()
# [1] 30
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54325348

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档