[Rd] Is it a good idea or even possible to redefine attach?

Grant Rettke gcr at wisdomandwonder.com
Tue Aug 5 23:37:03 CEST 2014


That is delightful.

When I run it like this:
• Start R
• Nothing in .Rprofile
• Paste in your code
╭────
│ gcrenv <- new.env()
│ gcrenv$attach.old <- attach
│ gcrenv$attach <- function(...){stop("NEVER USE ATTACH")}
│ base::attach(gcrenv, name="gcr", warn.conflicts = FALSE)
╰────
• I get exactly what is expected, I think
╭────
│ search()
╰────
╭────
│  [1] ".GlobalEnv"        "gcr"               "ESSR"
│  [4] "package:stats"     "package:graphics"  "package:grDevices"
│  [7] "package:utils"     "package:datasets"  "package:methods"
│ [10] "Autoloads"         "package:base"
╰────

Just to be sure:
• Is that what is expected?
• I am surprised because I thought that `gcr' would come first before
  `.GlobalEnv'
  • Perhaps I mis understand, as `.GlobalEnv' is actually the "REPL"?

My goal is to move that to my .Rprofile so that it is "always run" and I
can forget about it more or less.

Reading [this] I felt like `.First' would be the right place to put it,
but then read further to find that packages are only loaded /after/
`.First' has completed.  Curious, I tried it just to be sure. I am now
:).

This is the .Rprofile file:

╭────
│ cat(".Rprofile: Setting CMU repository\n")
│ r = getOption("repos")
│ r["CRAN"] = "http://lib.stat.cmu.edu/R/CRAN/"
│ options(repos = r)
│ rm(r)
│
│ .First <- function() {
│    «same code as above»
│ }
╰────

(I included the repository load, and understand it should not impact
things here)

This is run after normal startup of R:

╭────
│ search()
╰────
╭────
│  [1] ".GlobalEnv"        "package:stats"     "package:graphics"
│  [4] "package:grDevices" "package:utils"     "package:datasets"
│  [7] "gcr"               "package:methods"   "Autoloads"
│ [10] "package:base"
╰────

When I read this, I read it as:
• My rebind of `attach' occurs
• Then all of the packages are loaded and they are referring to
  my-rebound `attach'
• That is a problem because it *will* break package code
• Clearly me putting that code in `.Rprofile' is the wrong place.

What I am looking for now is the "right way" to achieve what is
demonstarted but automatically via a startup file.

My ideas:
• Manually paste the step each time
• Always use Emacs and ESS to run R and add a hook so that the code will
  be run after ESS loads
• Something I am missing


[this]
http://stat.ethz.ch/R-manual/R-devel/library/base/html/Startup.html
Grant Rettke | ACM, ASA, FSF, IEEE, SIAM
gcr at wisdomandwonder.com | http://www.wisdomandwonder.com/
“Wisdom begins in wonder.” --Socrates
((λ (x) (x x)) (λ (x) (x x)))
“Life has become immeasurably better since I have been forced to stop
taking it seriously.” --Thompson


On Tue, Aug 5, 2014 at 2:47 PM, Winston Chang <winstonchang1 at gmail.com> wrote:
> On Tue, Aug 5, 2014 at 1:49 PM, Grant Rettke <gcr at wisdomandwonder.com> wrote:
>>
>> Hi,
>>
>> Today I got curious about whether or not I /could/ remove `attach' from
>> my system so:
>> - Backed it up
>> - Implemented a new one
>> - Like this
>>
>> ,----
>> | attach.old <<- attach
>> | attach <<- function(...) {stop("NEVER USE ATTACH")}
>> `----
>>
>> I got the error:
>>
>> ,----
>> | Error: cannot change value of locked binding for 'attach'
>> `----
>>
>> If I unlock `attach' I assume that I could stomp on it... however is
>> that even a good idea?
>>
>> What will I break?
>
>
> If you change the base package environment's copy of `attach` (via
> `as.environment('package:base')`) , probably not much will break,
> except for your own code. If, on the other hand, you change the base
> namespace's copy of `attach` (via `asNamespace('base')`, any package
> that's subsequently loaded and uses `attach` would run into problems.
> Still, either way is probably not a good idea.
>
> I agree with Ista: assigning it yourself in the the global environment
> is a better idea. If you want to keep your global env clear of stuff
> like this, you can put it in an environment and attach that
> environment as a parent of global:
>
> e <- new.env()
> e$attach <-  function(...) {stop("NEVER USE ATTACH")}
> base::attach(e, name = "my_stuff", warn.conflicts = FALSE)
>
> # Test it out:
> attach()
>
> # You can see that the "my_stuff" env is the parent of global env
> search()
>
>
> -Winston



More information about the R-devel mailing list