7

What is the difference between assigning a value to a name in an environment and setting the environment of a variable? I couldn't figure it out from the documentation.

for example:

MyTestFunc = function(x)
{
    myVal = "abcde"

    # what is this doing?  why is myVal not in the global environment after 
    # this call? I see it adds an environment attribute to the variable, 
    # but what good is that?
    environment(myVal) = globalenv()

    assign( "myVal" , myVal , envir = globalenv() )

    # this seems to copy graphics:::rect to the current environment which seems 
    # to contradict the behavior of environment( myVal ) above
    environment( rect ) = environment()

    # this seems to do the same thing
    assign( "rect" , rect , envir = globalenv() )
}

# this prints out rect, but shows <environment: namespace: graphics>!
rect
smci
  • 32,567
  • 20
  • 113
  • 146
Suraj
  • 35,905
  • 47
  • 139
  • 250

2 Answers2

6

The assign function simply binds a name to a value in the specified environment.

But the environment replacement function does two things: its main purpose is to change the environment of a function closure. That environment is where the function's body code looks for global varables and functions. Normally, this envirionment is the one where the function was defined (so if you define it at the prompt it will use globalenv). As a "bonus", it just assigns the .Environment attribute for other object types. This is pretty useless for most objects, but is used by formulas.

The second thing is that it works like pretty much any other replacement function: if the name exists in the current environment it modifies it directly, otherwise it creates a local copy and modifies that. So in your case, it makes a local copy of the rect function and changes its environment. The original function remains unchanged.

# showing names replacement behavior
f <- function() {
  names(letters) <- LETTERS
  letters # the local modified copy
}
f() # prints changed letters
letters # unchanged
Tommy
  • 39,997
  • 12
  • 90
  • 85
1

Inside a function you asked and executed:

 # what is this doing?  why is myVal not in the global environment after this call?
    # I see it adds an environment attribute to the variable, but what good is that?
    environment(myVal) = globalenv()

So you didn't really do anything to the myVal object named "abcde" that was in the function. You instead created a new environment named "abcede" inside the function's environment. You then executed:

assign( "myVal" , myVal , envir = globalenv() )

It created a variable named "myVal" with the character mode value of "abcde" gathered from the local function environment, and put it into the global environment. It does now have an attribute named ".Environment". However, it remains unclear what your goals are, since environments are designed to be used to define the scope of functions. Assigning an environment to a data object is just weird. Variables are in environments, but there wouldn't seem to be a useful purpose in setting the environment of a variable. So I think the answer to your question: ...what good is that?" should be "it's not any good."

IRTFM
  • 258,963
  • 21
  • 364
  • 487
  • I can't seem to replicate your comments about environment(myVal) = globalenv(). If I did create an environment named "abcde" then where is that environment? How do I access it? It seems that I just added a .Environment attribute to myVal. And what explains environment( rect ) = environment()? My goals are simply to understand environments better so I can explore more advanced scenarios. – Suraj Dec 26 '11 at 16:44
  • You added an environment attribute to a character object. If you type "abcde" in at the console after executing a call to MyTestFunc(), you get output that includes: `attr(,".Environment") `. I have no idea how one would access that environment. I think this falls under the acronym DDT. – IRTFM Dec 26 '11 at 16:50
  • ah, got it! I've updated my code sample a bit. Could you take a look. Does the assign() and environment() calls for rect do the same thing? And why does the rect printout show a different environment than globalenv? – Suraj Dec 26 '11 at 17:44
  • I'll bet you never executed MyTestFunc after that definition. Just writing it in a function will not cause it to be executed. When I execute MyTestFunc() the environment of `rect` changes to – IRTFM Dec 26 '11 at 18:38
  • You are right, I never executed it. I just printed it out. For the first question, is it correct that assign() and environment() calls for rect do the same thing? – Suraj Dec 26 '11 at 18:47
  • With a slight "friendly amendment" I think that is right. Using the `environment<-` function with arguments `x` and `env` should have the same effect as `assign("x", x, env)` (as long as the 2nd and 3rd are not quoted) – IRTFM Dec 26 '11 at 18:59
  • so envrionment() doesn't really "move" the function to the specified envrionment, it just creates a copy there; its purpose is as a convenience function alternative to assign? Or is there some other use/scenario I haven't considered? – Suraj Dec 26 '11 at 19:05
  • No copies are created with `environment<-`. The search path, ie., the place(s) where it will first look for its arguments, gets changed. The `assign` function would be used if you wanted another copy made. – IRTFM Dec 26 '11 at 19:14