I want to take a user's code and convert reactive() calls into functions like this.
a <- reactive({
input$n * 100
})
and converts it to
a <- function() {
input$n *100
}
This is part of my shinyobjects package. I have put together a solution but I do not know if it is the right approach. Any help/feedback/resources would be appreciated. I couldn't figure out if rlang or lobstr might help.
code <-
"library(shiny)
input <- list(cty = 15)
df <- reactive({
x <- input$cty
mpg %>% filter(cty < x)
})
n_obs <- reactive(head(df()))"
all_expr <- parse(text = code)
reactive_to_function <- function(x) {
if (grepl("reactive\\(", as.character(x))) {
code_as_call <- as.call(x)[[1]]
get_symbol <- code_as_call[[2]]
get_formals <- code_as_call[[3]][[2]]
new_exp <-
as.expression(
bquote(
.(get_symbol) <- function() .(get_formals)
)
)
final_code <- new_exp
} else {
final_code <- x
}
final_code
}
works individually
reactive_to_function(all_expr[3])
#> expression(df <- function() {
#> x <- input$cty
#> mpg %>% filter(cty < x)
#> })
reactive_to_function(all_expr[4])
#> expression(n_obs <- function() nrow(df()))
and with a loop
exp_list <- expression()
for (i in seq_along(all_expr)) {
exp_list <-
append(
exp_list,
as.list(convert_assignments(all_expr[i])),
after = i - 1
)
}
exp_list
but can't get apply/map functions to work
lapply(all_expr, reactive_to_function)
#> Warning in if (grepl("reactive\\(", as.character(x))) {: the condition has
#> length > 1 and only the first element will be used
#> [[1]]
#> library(shiny)
#>
#> [[2]]
#> input <- list(cty = 15)
#>
#> [[3]]
#> df <- reactive({
#> x <- input$cty
#> mpg %>% filter(cty < x)
#> })
#>
#> [[4]]
#> n_obs <- reactive(nrow(df()))