1.Basic of enviroment

A environment, to adress it roughly, is a box of pointers pointing to the objects we need.These objects could include data types of course,but also functions. Remember, a function is also an object in Object Oriented Programming, R is a OOP(thought people use other language like python thinks R is not a “programming” language).

Since it is all pointers in the environment, it is obvious that two pointers can point to the same object, and two pointers can point to different obejct but with the same content.Any object that within the memory but do not have a pointer pointing to it would be collected by the garbage collector.

Now I have just started R and use search() to see the envrinments I have.

search()
## [1] ".GlobalEnv"        "package:stats"     "package:graphics" 
## [4] "package:grDevices" "package:utils"     "package:datasets" 
## [7] "package:methods"   "Autoloads"         "package:base"

and if I add a package?

library(ggplot2)
search()
##  [1] ".GlobalEnv"        "package:ggplot2"   "package:stats"    
##  [4] "package:graphics"  "package:grDevices" "package:utils"    
##  [7] "package:datasets"  "package:methods"   "Autoloads"        
## [10] "package:base"

add another one.

library(data.table)
search()
##  [1] ".GlobalEnv"         "package:data.table" "package:ggplot2"   
##  [4] "package:stats"      "package:graphics"   "package:grDevices" 
##  [7] "package:utils"      "package:datasets"   "package:methods"   
## [10] "Autoloads"          "package:base"

It is obvious that new package creates new environment and is added in a row between global environment and the base environment of R.
This brings us down to the issue of parent environment.

emptyenv() is the parent of all environments and it has no parent.
All enviroment know its parent but has no idea who its children is. To create a new environment:(it could not be searched,still belongs to GlobalEnv)

new<-new.env()
parent.env(new)
## <environment: R_GlobalEnv>

See, I created it within the most environment we see every day—The Global Environment. And I can assign pointers to new objects with in the environment and use ls() to inspect them.

new$aa<-1
new$bb<-"naive"
ls(new,all.names = TRUE)
## [1] "aa" "bb"

some reference method to get the objects in the environment.

ls.str(new)
## aa :  num 1
## bb :  chr "naive"
new$aa
## [1] 1
get("bb",envir = new)
## [1] "naive"

to remove the objects, use rm()

rm("aa",envir = new)
ls.str(new)
## bb :  chr "naive"

aa is deleted

To see is a object exist,we could use exists(), it will continue to search up the parent environment.

x<-"too simple" 
exists("x",envir = new)#keep searching parents until found
## [1] TRUE
exists("x",envir = new,inherits = FALSE)#just search in "new""
## [1] FALSE

one more thing, environment() is the current environment that we work in, most times it will be equal to the global environment.
use identical() to check.

identical(environment(),globalenv())
## [1] TRUE

2.Explore enviroments

A very useful package in environments and momory manipulation is pryr.

library(pryr)
search()# see it been added
##  [1] ".GlobalEnv"         "package:pryr"       "package:data.table"
##  [4] "package:ggplot2"    "package:stats"      "package:graphics"  
##  [7] "package:grDevices"  "package:utils"      "package:datasets"  
## [10] "package:methods"    "Autoloads"          "package:base"

where() could tell us which environment the object is in. By saying objects I mean data and functions.
Notice:The current environment is the globalEnv, and new is a child of global, so use where(“bb”) will return a error.
Because it only search up to the parent but do not search down to the child.

where("x")
## <environment: R_GlobalEnv>
where("ggplot")
## <environment: package:ggplot2>
## attr(,"name")
## [1] "package:ggplot2"
## attr(,"path")
## [1] "C:/Users/Steven/Documents/R/win-library/3.2/ggplot2"
where("sum")
## <environment: base>
where("mean")
## <environment: base>
where("View")
## <environment: package:utils>
## attr(,"name")
## [1] "package:utils"
## attr(,"path")
## [1] "C:/Program Files/R/R-3.2.4/library/utils"
where("new")
## <environment: R_GlobalEnv>
try(where("bb"))

3.Environment and functions

The most important part about learning environment is its application with functions.
Though I can create new child environment with command new.env(), but there is no use of it. Most of the times, environments are created without us noticing by us using functions.
The types are: enclosing,binding,execution and calling.
1.enclosing environment: It is where the function is created. And it is unique to every function.
2.Binding environment: if we use <- to name a function, it will difine a binding environment.
3.If we call a function when using it, R would create a temporary execution environment to store local variables.
4.Every execution environment is associated with a calling environment,which tells where the function is called.
(The above was learnt from Advanced R by Hadley Wickham)

The relationship above is a little messy. But the scoping difference is quite obvious below.

test<-function(){
  x<-10
  function(){
    x*10
  }
}

test is a function that returns a function. It is the fucntional programming feature of R.

where("test")
## <environment: R_GlobalEnv>
environment(test)
## <environment: R_GlobalEnv>

The enclosing envirment of test is global environment.

x<-20
where("x")
## <environment: R_GlobalEnv>
ss<-test()
ss()
## [1] 100

while x=20 is in global environment, when ss in created it only takes the x=10 in the execution environment of test where x is assigned to 10. If one is familiar with C++ or java, it is merely the difference of local variable and global variable, only different in that R uses a sub-environment(namespace) for the same name.

`:)`<-"happy"
`:)`
## [1] "happy"

The assignment <- that we use every day acutaully creates an object in the current environment, which in most cases are the global environment. The <<- operator will make the variable up till the parent envirment.

new$x<-10
x<-15
where("x")
## <environment: R_GlobalEnv>
x<<-20
where("x")
## <environment: R_GlobalEnv>

Something like a constant varibale.

Now in R modify dataframe no longer makes deep copies, which saved a lot of time. But environment has the advantage of using reference instead of deep copy.

y<-33
where("y")
## <environment: R_GlobalEnv>
dd<-new.env()
get("y",envir = dd) #automatically search up since global environment is the parent and contains y=33
## [1] 33
try(get("y",envir = dd,inherits = FALSE)) #will return error

#alternatively
ee<-new.env(parent = emptyenv())#so ee would search up to global env
try(get("y",ee))

That’s all for now.