Search code examples
rpurrrr-environmentr-glue

Partialised glue function does not work when called in different environment


I've partialised the glue function in a project I'm working on so that we can use agreed-on delimiters without having to tell glue about them all the time. But when we go to use the partialised function inside another function, it stops working:

library(purrr)
library(glue)

glue_query <- partial(glue, .open = "<<", .close = ">>")

# case 1: use partialised function in same scope
x <- 15
glue_query("There are <<x>> apples here!")
#> There are 15 apples here!

# case 2: use partialised function in different scope
myfunc_partialised <- function(y) {
  glue_query("The thing I called y is actually <<y>>")
}
myfunc_partialised(15)
#> Error in eval(parse(text = text, keep.source = FALSE), envir): object 'y' not found

# case 3: use function directly
myfunc_regular <- function(z) {
  glue("The thing I called z is actually <<z>>", .open = "<<", .close = ">>")
}
myfunc_regular(15)
#> The thing I called z is actually 15

Created on 2021-07-09 by the reprex package (v2.0.0)

I get the sense that glue_query is looking for objects to interpolate in the environment it was defined in, rather than in the environment it's called in. Is that's what happening here? Can I direct it to use the calling environment? I'd like to use it throughout my package!

EDIT: I understand that glue has an .envir argument that controls which environment the expressions are evaluated in, but I'm not quite sure what to use to ensure it plays nice here!


Solution

  • It does seem that partial() makes it much more difficult to get the correct environment. Instead you can write your own wrapper

    glue_query <- function(..., .open = "<<", .close = ">>", .envir=parent.frame()) {
      glue(..., .open=.open, .close=.close, .envir=.envir)
    }
    

    This will work with both the test cases you provided.