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

2014-08-10 Thread Grant Rettke
Thank you for that pleasant and concise explanation!

I will keep at it.
Grant Rettke | ACM, ASA, FSF, IEEE, SIAM
g...@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 7:54 PM, Winston Chang winstoncha...@gmail.com wrote:
 On Tue, Aug 5, 2014 at 4:37 PM, Grant Rettke g...@wisdomandwonder.com wrote:

 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] .GlobalEnvgcr   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] .GlobalEnvpackage: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.


 That order for search path should actually be fine. To understand why,
 you first have to know the difference between the _binding_
 environment for an object, and the _enclosing_ environment for a
 function.

 The binding environment is where you can find an object. For example,
 in the global env, you have a bunch bindings (we often call them
 variables), that point to various objects - vectors, data frames,
 other environments, etc.

 The enclosing environment for a function is where the function runs
 in when it's called.

 Most R objects have just a binding environment (a variable or
 reference that points to the object); functions also have an enclosing
 environment. These two environments aren't necessarily the same.

 When you run search(), it shows the set of environments where R will
 look for an object of a given name, when you run stuff at the console
 (and are in the global env). The trick is that, although you can find
 a function (they are bound bound) in one of these _package_
 environments, those functions run in (are enclosed by) a different
 environment: the a corresponding _namespace_ environment.

 The way that a namespace environment is set up with the arrangement of
 its ancestor environments, it will find the base namespace version of
 `attach` before it finds yours, even if your personal gcr environment
 comes early in the search path.

 =
 # Here's an example to illustrate. The `utils::alarm` function calls
 `cat`, which is in base.

 alarm
 # function ()
 # {
 # cat(\a)
 # flush.console()
 # }
 # environment: namespace:utils


 # Running it makes the screen flash or beep
 alarm()
 # [screen flashes]


 # We'll put a replacement version of cat early in the search path,
 between utils and base
 my_stuff - new.env()
 my_stuff$cat - function(...) stop(Tried to call cat)
 base::attach(my_stuff, pos=length(search()) - 1, name=my_stuff)

 search()
 #  [1] .GlobalEnvtools:rstudio package:stats
 package:graphics
 #  [5] package:grDevices package:utils package:datasets
 package:methods
 #  [9] my_stuff  Autoloads package:base

 # Calling cat from the console gives the error, as expected
 cat()
 # Error in cat() : Tried to call cat

 # But when we run alarm(), it still gets the real version of `cat()`,
 # because it finds the the original base namespace version of cat
 # before it finds yours.
 alarm()
 # [screen flashes]

 ==

 You can even 

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

2014-08-10 Thread Grant Rettke
As it turns out, my approach was a bit aggressive. A critical package
was using it and could see my new attach!

I will just warn, and encourage:

.First - function() {
gcr - new.env()
gcr$unsafe.attach - attach
gcr$attach - function(...) {
warning(NEVER USE ATTACH! Use `unsafe.attach` if you must.)
unsafe.attach(...)
}
base::attach(gcr, name=gcr, warn.conflicts = FALSE)
}
Grant Rettke | ACM, ASA, FSF, IEEE, SIAM
g...@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 Sun, Aug 10, 2014 at 9:13 AM, Grant Rettke g...@wisdomandwonder.com wrote:
 Thank you for that pleasant and concise explanation!

 I will keep at it.
 Grant Rettke | ACM, ASA, FSF, IEEE, SIAM
 g...@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 7:54 PM, Winston Chang winstoncha...@gmail.com wrote:
 On Tue, Aug 5, 2014 at 4:37 PM, Grant Rettke g...@wisdomandwonder.com 
 wrote:

 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] .GlobalEnvgcr   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] .GlobalEnvpackage: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.


 That order for search path should actually be fine. To understand why,
 you first have to know the difference between the _binding_
 environment for an object, and the _enclosing_ environment for a
 function.

 The binding environment is where you can find an object. For example,
 in the global env, you have a bunch bindings (we often call them
 variables), that point to various objects - vectors, data frames,
 other environments, etc.

 The enclosing environment for a function is where the function runs
 in when it's called.

 Most R objects have just a binding environment (a variable or
 reference that points to the object); functions also have an enclosing
 environment. These two environments aren't necessarily the same.

 When you run search(), it shows the set of environments where R will
 look for an object of a given name, when you run stuff at the console
 (and are in the global env). The trick is that, although you can find
 a function (they are bound bound) in one of these _package_
 environments, those functions run in (are enclosed by) a different
 environment: the a corresponding _namespace_ environment.

 The way that a namespace environment is set up with the arrangement of
 its ancestor environments, it will find the base namespace version of
 `attach` before it finds yours, even if your personal gcr environment
 comes early in the search path.

 =
 # Here's an example to illustrate. The `utils::alarm` function calls
 `cat`, which is in base.

 alarm
 # function ()
 # {
 # cat(\a)
 # flush.console()
 # }
 # environment: namespace:utils


 # Running it makes the screen flash or beep
 alarm()
 # [screen flashes]


 # We'll put a replacement 

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

2014-08-05 Thread Grant Rettke
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?

My goal was never to allow `attach' in my system, but it was just an
idea.

Kind regards,

Grant Rettke | ACM, ASA, FSF, IEEE, SIAM
g...@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

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


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

2014-08-05 Thread Ista Zahn
On Tue, Aug 5, 2014 at 2:49 PM, Grant Rettke g...@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)}
 `

Just masking it with your own function, e.g.,

attach - function(...) {stop(NEVER USE ATTACH)}

should be enough to discourage you from using it.


 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?

Anything that uses attach.


 My goal was never to allow `attach' in my system, but it was just an
 idea.

 Kind regards,

 Grant Rettke | ACM, ASA, FSF, IEEE, SIAM
 g...@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

 __
 R-devel@r-project.org mailing list
 https://stat.ethz.ch/mailman/listinfo/r-devel

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


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

2014-08-05 Thread Winston Chang
On Tue, Aug 5, 2014 at 1:49 PM, Grant Rettke g...@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

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


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

2014-08-05 Thread Grant Rettke
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] .GlobalEnvgcr   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] .GlobalEnvpackage: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
g...@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 winstoncha...@gmail.com wrote:
 On Tue, Aug 5, 2014 at 1:49 PM, Grant Rettke g...@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

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


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

2014-08-05 Thread Winston Chang
On Tue, Aug 5, 2014 at 4:37 PM, Grant Rettke g...@wisdomandwonder.com wrote:

 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] .GlobalEnvgcr   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] .GlobalEnvpackage: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.


That order for search path should actually be fine. To understand why,
you first have to know the difference between the _binding_
environment for an object, and the _enclosing_ environment for a
function.

The binding environment is where you can find an object. For example,
in the global env, you have a bunch bindings (we often call them
variables), that point to various objects - vectors, data frames,
other environments, etc.

The enclosing environment for a function is where the function runs
in when it's called.

Most R objects have just a binding environment (a variable or
reference that points to the object); functions also have an enclosing
environment. These two environments aren't necessarily the same.

When you run search(), it shows the set of environments where R will
look for an object of a given name, when you run stuff at the console
(and are in the global env). The trick is that, although you can find
a function (they are bound bound) in one of these _package_
environments, those functions run in (are enclosed by) a different
environment: the a corresponding _namespace_ environment.

The way that a namespace environment is set up with the arrangement of
its ancestor environments, it will find the base namespace version of
`attach` before it finds yours, even if your personal gcr environment
comes early in the search path.

=
# Here's an example to illustrate. The `utils::alarm` function calls
`cat`, which is in base.

alarm
# function ()
# {
# cat(\a)
# flush.console()
# }
# environment: namespace:utils


# Running it makes the screen flash or beep
alarm()
# [screen flashes]


# We'll put a replacement version of cat early in the search path,
between utils and base
my_stuff - new.env()
my_stuff$cat - function(...) stop(Tried to call cat)
base::attach(my_stuff, pos=length(search()) - 1, name=my_stuff)

search()
#  [1] .GlobalEnvtools:rstudio package:stats
package:graphics
#  [5] package:grDevices package:utils package:datasets
package:methods
#  [9] my_stuff  Autoloads package:base

# Calling cat from the console gives the error, as expected
cat()
# Error in cat() : Tried to call cat

# But when we run alarm(), it still gets the real version of `cat()`,
# because it finds the the original base namespace version of cat
# before it finds yours.
alarm()
# [screen flashes]

==

You can even alter package environments without affecting the
corresponding namespace environment. The exception to the package and
namespace environments being distinct is the base environment; change
one and you change the other. (I just realized this and have to
retract my earlier statement about the behavior being different if
change attach in the base package env vs. the base namespace env.)

-Winston

__
R-devel@r-project.org mailing list