4

a.k.a playing with fire...

The following does not work:

rstd.obj <- as.environment("tools:rstudio")
detach("tools:rstudio")
attach(rstd.obj, name="tools:rstudio")

Well, it seems to work, but then all sorts of weird errors start popping up. The problem is that very annoyingly (though I'm sure for a very good reason) attach makes a copy of the environment and attaches that, instead of attaching the environment directly:

rstd.obj
# <environment: 0x000000000930edd0>
# attr(,"name")
# [1] "tools:rstudio"
as.environment("tools:rstudio")
# <environment: 0x000000000a21b4c8>
# attr(,"name")
# [1] "tools:rstudio"

Notice how the environments are actually different (this is also confirmed if you look at the source code for do_attach in src/main/envir.c@2124(R3.0.2) where the copy is made).

This, however, works totally fine (after restarting RStudio to reset everything):

rstd.obj <- as.environment("tools:rstudio")
rstd.parent <- as.environment("package:stats")  # this was #3 on search path for me
detach("tools:rstudio")

# WARNING: YOU'RE PLAYING WITH FIRE IF YOU RUN THIS, DO
# SO AT YOUR OWN RISK:

parent.env(.GlobalEnv) <- rstd.obj
parent.env(rstd.obj) <- rstd.parent

Instead of using detach/attach, we just detach, and forcibly insert the object back into the search path using parent.env<-. On the flipside, I'm guessing doing the above is probably close to what R Core had in mind when they warned in ?parent.env:

The replacement function parent.env<- is extremely dangerous as it can be used to destructively change environments in ways that violate assumptions made by the internal C code. It may be removed in the near future.

Another alternative to get around this problem is to use detach/attach, but then cycle through all the functions in the tools:rstudio environment on the search path and reset their environments to the copy of the original environment now on the search path (incidentally, this is why Rstudio starts breaking: the function environments are still the object removed from the search path, but that environment is not in the search path anymore, only a copy of it). This feels incredibly hacky though.

Also, if anyone knows more details about what the "assumptions made by the internal C code" are I'd be very interested to hear them. Obviously, we could introduce circularities in the search path (no, I didn't accidentally just do that messing around with these examples...), but are there other problems as well?

EDIT: regarding the above, super useful tidbit from R-devel:

I'd like to propose a change to the R language so that calling 'parent.env<-' on a package namespace or package imports is a runtime error. ... I'd also like to make calling parent.env<- on an environment on the call stack an error, for the same reasons, but it's not so obvious to me how to implement that efficiently right now. Could we at least document that as being 'undefined behaviour'?

And Luke Tierney's answer:

I'll look into it

This seems to confirm the concern is changing the call stack in call or search path in a way R may not track, as opposed to generally thinking parent.env<- is dangerous for other environment chains (clearly reading b/w lines here).

BrodieG
  • 51,669
  • 9
  • 93
  • 146
  • yow. What are you trying to accomplish?? – Ben Bolker Oct 14 '14 at 17:51
  • 2
    @BenBolker, I'm trying to automatically create a clean environment by resetting the search path to be bare bones (i.e. ending at `package:stats`), but having the ability to undo that change, which unfortunately requires being able to re-attach `tools:rstudio`. – BrodieG Oct 14 '14 at 17:53
  • have you looked into whatever machinery underlies the "Restart R" button in RStudio? It looks like it's `.rs.restartR`, which has an `afterRestartCommand` option too ... – Ben Bolker Oct 14 '14 at 17:59
  • @BenBolker, interesting option. One problem is this will not address other environments that are not automatically attached on start-up like "tools:rstudio" is. I'd like a way of doing this that can restore the full state of the search path, irrespective of what it was beforehand. Also, this should work on non RStudio environments so I may not be able to rely on those hooks (**[this](http://stackoverflow.com/questions/6313079/quit-and-restart-a-clean-r-session-from-within-r)** might be an option for the last point). – BrodieG Oct 14 '14 at 18:26

0 Answers0