Skip to content

Instantly share code, notes, and snippets.

@jrnold
Created June 28, 2018 01:32
Show Gist options
  • Save jrnold/346b2beb3eaab4a7e35bcbf2871f89a9 to your computer and use it in GitHub Desktop.
Save jrnold/346b2beb3eaab4a7e35bcbf2871f89a9 to your computer and use it in GitHub Desktop.
Is an R environment an ancestor of another
# test if env has parent
has_ancestor <- function(env, ancestor, last = global_env(), n = NULL) {
# special cases
if (!typeof(env) == "environment") {
abort("`env` must be an environment")
}
if (is_empty_env(env)) {
return(FALSE)
}
if (!typeof(ancestor) %in% c("environment", "NULL")) {
abort("`ancestor` must be `NULL` or an environment")
}
if (is_empty_env(ancestor) || is.null(ancestor)) {
return(TRUE)
}
if (is_reference(env, ancestor)) {
return(TRUE)
}
if (!typeof(last) %in% c("environment", "NULL")) {
abort("`last` must be `NULL` or an environment")
}
if (!is.null(n) || is_scalar_integerish(n)) {
abort("`n` must be a scalar integer or `NULL`")
}
n <- n %||% env_depth(env)
if (n < 0L) {
abort("`n` must be an integer greater than or equal to zero")
}
i <- 0L
while (TRUE) {
i <- i + 1L
# reached maximum depth
if (i > n) {
return(FALSE)
}
parent <- env_parent(env)
# found an ancestor!
if (is_reference(parent, ancestor)) {
return(TRUE)
}
# reached last environment
if (is_reference(parent, last) || is_empty_env(parent)) {
return(FALSE)
}
env <- parent
}
}
has_ancestor(bottom, top)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment