Как позволить функции, определенной в глобальной среде, обращаться к переменным, определенным в среде ее вызывающей функции?
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
Я хочу создать функцию, которая может быть использована внутри функции (которая используется для создания веб-API с сантехником).
Функция используется для получения результата sql. Для построения запроса sql нужна некоторая переменная.
Приведенный выше код не работает. Кажется, проблема в окружающей среде.
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()
}
Это не решение "общего назначения", но та же основная идея применима и в других местах. Вам нужно явно обратиться к вызывающей среде, когда вам это нужно.