Reactive object bindings in a non-shiny context

前端 未结 5 893
轮回少年
轮回少年 2021-02-02 12:25

Actual question

How could you either approximate the reactive environment/behavior established by shiny functions or possibly even use these very functions in a

5条回答
  •  盖世英雄少女心
    2021-02-02 13:20

    Thanks to Rappster, Joe and Robert, your conversations have really benefited me a lot.

    I have just writen a small tool to build a cacheable function using the following idea:

    library(shiny)
    gen.f <- function () {
        reactv <- reactiveValues()
    
        a <- reactive({ print('getting a()'); reactv$x + 1 })
        b <- reactive({ print('getting b()'); reactv$y + 1 })
        c <- reactive({ print('getting c()'); a() + b() })
    
        function (x.value, y.value) {
            reactv$x <<- x.value
            reactv$y <<- y.value
            isolate(c())
        }
    }
    f <- gen.f()
    

    In the above example, the parent environment of the returned function was used to store the reactive values and the reactive expressions.

    By doing so, the returned function will have the ability to cache its intermediate results and do not need to recalculate them if the function is further called with the same arguments. The underlying reactive expressions are wrapped inside and the function can be used as normal R functions.

    > f(6,9)
    [1] "getting c()"
    [1] "getting a()"
    [1] "getting b()"
    [1] 17
    > f(6,9)
    [1] 17
    > f(6,7)
    [1] "getting c()"
    [1] "getting b()"
    [1] 15
    

    Based on this idea, I wrote a tool to help generate this kind of cacheable function with the following syntax. You can see my repo at https://github.com/marlin-na/reactFunc

    myfunc <- reactFunc(
        # ARGV is the formal arguments of the returned function
        ARGV = alist(x = , y = ),
    
        # These are reactive expressions in the function argument form
        a = { print('getting a()'); x + 1 },
        b = { print('getting b()'); y + 1 },
        ans = { print('getting ans()'); a() + b() }
    )
    > myfunc(6, 9)
    [1] "getting ans()"
    [1] "getting a()"
    [1] "getting b()"
    [1] 17
    > myfunc(6, 9)
    [1] 17
    > myfunc(6, 7)
    [1] "getting ans()"
    [1] "getting b()"
    [1] 15
    

    Regards,

    M;

提交回复
热议问题