【问题标题】:How to let function defined in global environment access variables defined in its calling function's environment?如何让全局环境中定义的函数访问其调用函数环境中定义的变量?
【发布时间】:2018-09-05 14:59:12
【问题描述】:
connect_dw <- function() {
  DBI::dbConnect(RSQLite::SQLite(), ":memory:")
}

fetch_sql_res <- function(key, ...) {
  query_list <- list(...)
  query_sql_res <- function(.query_list = query_list, .db_connect_f = connect_dw) {
    con <- .db_connect_f()
    res <- purrr::map(.query_list, glue::glue_sql, .con = con ) %>%
      purrr::map(purrr::partial(DBI::dbGetQuery, conn = con))
    DBI::dbDisconnect(con)
    res
  }

 ## if key exists in redis cache, fetch it from redis.
 ## If not, call the function to query database

  query_sql_res()

}

#' testing
#' @serializer unboxedJSON
#' @get /test_db
test_db <- function() {
  userid <- 10

  fetch_sql_res(df = "SELECT {userid}")
}

错误信息:

 Error in eval(parse(text = text, keep.source = FALSE), envir) : 
  object 'userid' not found

我想创建一个可以在函数内部使用的函数(用于使用管道工创建 web api)。

该函数用于获取sql结果。它需要一些变量来构造 sql 查询。

上面的代码不起作用。问题似乎与环境有关。

【问题讨论】:

    标签: r plumber


    【解决方案1】:

    所有 R 函数都是词法范围的,这意味着它们从定义函数的位置继承变量,而不是从调用函数的位置继承变量。您无法更改此默认行为,因为它会破坏很多东西。因此,当您评估需要不同环境的函数调用时,您只需要小心指定正确的环境。

    在这种情况下,问题似乎在于glue::glue_sql 无法找到变量。该函数有一个.envir= 参数,告诉它在哪里寻找变量。您只需要将调用环境显式传递给该函数。例如

    fetch_sql_res <- function(key, ...) {
      query_list <- list(...)
      calling_env <- parent.frame()
      query_sql_res <- function(.query_list = query_list, .db_connect_f = connect_dw) {
        con <- .db_connect_f()
        res <- purrr::map(.query_list, glue::glue_sql, .con = con, .envir=calling_env ) %>%
          purrr::map(purrr::partial(DBI::dbGetQuery, conn = con))
        DBI::dbDisconnect(con)
        res
      }
      query_sql_res()
    }
    

    这不是“通用”解决方案,但相同的基本思想也适用于其他地方。需要时需要显式引用调用环境。

    【讨论】:

      猜你喜欢
      • 2017-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-15
      • 1970-01-01
      相关资源
      最近更新 更多