Finding the source environment of the arguments ... (points) of the call

I want to find the environment from which ...call arguments (points) arise .

Scenario

For example, consider a function

foo <- function(x, ...) {
  # do something
}

We need a function env_dots()that we call from foo()that finds the source environment ...in the call foo(), even when the call is foo()deeply nested. That is, if we define

foo <- function(x, ...) {
  # find the originating environment of '...'
  env <- env_dots()

  # do something
}

and insert a call foofor example

baz <- function(...) {
  a <- "You found the dots"
  bar(1, 2)
}
bar <- function(...)
  foo(...)

then the call baz()should return the environment in which it arises ...in the (nested) call foo(...): this is the environment in which the call is made bar(1, 2), because 2(but not 1) it is passed to the points foo. In particular, we should get

baz()$a
#> [1] "You found the dots"

Naive implementation env_dots()

- env_dots(), , , ... , .

env_dots():

# mc: match.call() of function from which env_dots() is called
env_dots <- function(mc) {
  # Return NULL if initial call invokes no dots
  if (!rlang::has_name(mc, "...")) return(NULL)

  # Otherwise, climb the call stack until the dots origin is found
  stack <- rlang::call_stack()[-1]
  l <- length(stack)
  i <- 1
  while (i <= l && has_dots(stack[[i]]$expr)) i <- i + 1
  # return NULL if no dots invoked
  if (i <= l) stack[[i + 1]]$env else NULL
}

# Does a call have dots?
has_dots <- function(x) {
  if (is.null(x))
    return(FALSE)
  args <- rlang::lang_tail(x)
  any(vapply(args, identical, logical(1), y = quote(...)))
}

:

foo <- function(x, ...)
  env_dots(match.call(expand.dots = FALSE))

baz()$a
#> [1] "You found the dots"

bar(1, 2)  # 2 gets passed down to the dots of foo()
#> <environment: R_GlobalEnv>

bar(1)     # foo() captures no dots
#> NULL

env_dots() .

  • env_dots() rlang / R?

  • match.call() env_dots()? match.call(sys.function(-1), call = sys.call(-1), expand.dots = FALSE) .

. rlang::quos(...), quosures (, ).

+4

Source: https://habr.com/ru/post/1680171/


All Articles