Created
August 7, 2012 01:17
-
-
Save wch/3280369 to your computer and use it in GitHub Desktop.
Sample code for unlocking environments in R
This file contains hidden or 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
library(inline) | |
inc <- ' | |
/* This is taken from envir.c in the R 2.15.1 source */ | |
#define FRAME_LOCK_MASK (1<<14) | |
#define FRAME_IS_LOCKED(e) (ENVFLAGS(e) & FRAME_LOCK_MASK) | |
#define UNLOCK_FRAME(e) SET_ENVFLAGS(e, ENVFLAGS(e) & (~ FRAME_LOCK_MASK)) | |
' | |
src <- ' | |
if (TYPEOF(env) == NILSXP) | |
error("use of NULL environment is defunct"); | |
if (TYPEOF(env) != ENVSXP) | |
error("not an environment"); | |
UNLOCK_FRAME(env); | |
// Return TRUE if unlocked; FALSE otherwise | |
SEXP result = PROTECT( Rf_allocVector(LGLSXP, 1) ); | |
LOGICAL(result)[0] = FRAME_IS_LOCKED(env) == 0; | |
UNPROTECT(1); | |
return result; | |
' | |
unlockEnvironment <- cfunction(signature(env = "environment"), | |
includes = inc, | |
body = src) | |
unlockEnvironment(new.env()) # TRUE | |
unlockEnvironment('foo') # error | |
# Wrapper function should return(invisible(TRUE)) if successful, error otherwise. | |
# Wrapper function should also check type | |
# ============== test unlocking bindings | |
e <- new.env() | |
e$x <- 5 | |
e$x # 5 | |
lockEnvironment(e, bindings = TRUE) | |
e$x <- 6 # ERROR | |
environmentIsLocked(e) # TRUE | |
e$y <- 6 # ERROR | |
bindingIsLocked('x', e) # TRUE | |
unlockBinding('x', e) | |
bindingIsLocked('x', e) # FALSE | |
e$x <- 7 # OK | |
# Re-lock environment and bindings | |
lockEnvironment(e, bindings = TRUE) | |
e$y <- 6 # ERROR | |
# Run our custom function | |
unlockEnvironment(e) # TRUE | |
environmentIsLocked(e) # FALSE | |
e$y <- 8 # OK | |
bindingIsLocked('x', e) # TRUE | |
e$x <- 7 # ERROR | |
unlockBinding(ls(e, all.names=TRUE), e) | |
e$x <- 7 # OK | |
bindingIsLocked('x', e) # FALSE | |
bindingIsLocked('y', e) # FALSE | |
e$y <- 8 | |
e$z <- 9 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Soon it will be is 3 years since that gist, maybe there is some better way? without inline dependency?