Created
June 28, 2018 01:32
-
-
Save jrnold/346b2beb3eaab4a7e35bcbf2871f89a9 to your computer and use it in GitHub Desktop.
Is an R environment an ancestor of another
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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