How to Unlock Environment in R

Get environment of function from within the function

Ok, found the solution:

e$f <- function() unlockBinding("b", parent.env(environment()))

should do the trick.

changing functions and unlocking bindings in R

If you want, you can use the godmode package from Github:

# save original version
orig <- graphics::boxplot.default

# devtools::install_github("miraisolutions/godmode")
godmode:::assignAnywhere("boxplot.default", boxplot.default_new)

# switch back
godmode:::assignAnywhere("boxplot.default", orig)

boxplot.default_new should then be your re-write of boxplot.default, possibly including your function myboxplot.stats (maybe even rename it) and the call to it.

Problems with unlocking binding (in R) after running code from c++

Just received a solution from my professor:

"Instead of treating weights and trace as global variables that are modified from inside the batch function, we can pass them into the function and return them out:"

batch <- function(weights, trace, n.training){ 

for(i in 1:n.training){
g <- input.correlation()
for(o in 1:nrow(g)){
result <- traceUpdate(g[o,], trace, weights, trace.param, learning.rate)
weights <- result$weights
trace <- result$trace
}
}
return(list(weights=weights, trace=trace))
}

result <- batch(weights, trace, 50)
weights <- result$weights
trace <- result$trace

Capturing the global environment

This function avoids the side effects as much as possible:

  library(ggplot2)
library(magrittr)
library(tibble)
my.better.plot <- function(){
x.coords <- 1
y.coords <- 1
environment(package.plot) <- environment()

bmp(tempfile())
package.plot()
dev.off()

print(tibble(x.coords,y.coords) %>% ggplot(aes(x=x.coords,y=y.coords))+geom_point()) # etc.
}

my.better.plot()
#creates only the ggplot in the current device

ls(globalenv())
#[1] "my.better.plot" "package.plot" "the.data"

Assigning a locked variable in an R package

Mostly not answering your question. I agree with @IShouldByABoat that there's more going on, a package with the simple structure you indicate doesn't generate the error you see for me. Likely you're trying to modify True elsewhere in your code (!) or perhaps you've got some cruft in your .Rprofile or .RData file that is interfering -- run your check as R --vanilla CMD check.

Functions and symbols are defined in a package name space, for instance

library(plyr)             ## load package name space, attach to the search() path
getNamespace(plyr) ## package name space
ls(getNamespace(plyr)) ## symbols defined in the name space
plyr::llply ## definition of `llply` in the name space

The package name space is locked after it has been loaded

assign("llply", identity, envir=getNamespace("plyr"))
## Error in assign("llply", identity, envir = getNamespace("plyr")) :
## cannot change value of locked binding for 'llply'

Assigning to a similarly named variable at the command line creates a new variable in the .GlobalEnv (the first location on the search() path) rather than modifying the variable in the package name space

ls()               ## no symbol 'llply' in .GlobalEnv
llply <- identity ## new symbol 'llply' in .GlobalEnv
llply(10) ## use first llply function in search(), i.e., in .GlobalEnv
plyr::llply(10) ## circumvent search path and use llply from plyr name space

So code such as

True <- TRUE
lockBinding("True", environment())

only adds a locked binding from the time True is created until the package is loaded; after that the binding is locked anyway.

Maybe you want to create a variable True in the user's .GlobalEnv, and make that so that it cannot be changed. This has to be done when the package is load'ed (or attach'ed), when the user's current .GlobalEnv is visible, with something like

.onAttach <- function(...) {
assign("True", TRUE, .GlobalEnv)
lockBinding("True", .GlobalEnv)
}

This only locks the binding in the .GlobalEnv so it cannot be changed, but does not stop the user from removing it (e.g., using rm("True")). Messing with your user's .GlobalEnv will likely also serve to irritate your user more than further your programming agenda.

How to modify unexported object in a package

As it turns out, I only had to remove the unlockBinding, assign and lockBinding calls.

bar <- function(x) x + 1
assignInNamespace("C_rf", bar, ns="stats", pos="package:stats")

stats:::C_rf
# function(x) x + 1

rf(3, 2, 2)
#Error in .Call(C_rf, n, df1, df2) :
# first argument must be a string (of length 1) or native symbol reference


Related Topics



Leave a reply



Submit