Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
R in Action, Second Edition.pdf
Скачиваний:
540
Добавлен:
26.03.2016
Размер:
20.33 Mб
Скачать

Working with environments

475

20.2 Working with environments

An environment in R consists of a frame and enclosure. A frame is set of symbol-value pairs (object names and their contents), and an enclosure is a pointer to an enclosing environment. The enclosing environment is also called the parent environment. R allows you to manipulate environments from within the language, resulting in fine-grained control over scope and the segregation of functions and data.

In an interactive session, when you first see the R prompt, you’re in the global environment. You can create a new environment with the new.env() function and create assignments in that environment with the assign() function. Object values can be retrieved from an environment using the get() function. Here’s an example:

>x <- 5

>myenv <- new.env()

>assign("x", "Homer", env=myenv)

>ls()

[1] "myenv" "x"

>ls(myenv) [1] "x"

>x

[1] 5

> get("x", env=myenv) [1] "Homer"

An object called x exists in the global environment and has the value 5. An object also called x exists in the environment myenv and has the value “Homer”.

In addition to using the assign() and get() functions, you can use the $ notation. For example,

>myenv <- new.env()

>myenv$x <- "Homer"

>myenv$x

[1] "Homer"

produces the same results.

The parent.env() function displays the parent environment. Continuing the example, the parent environment for myenv is the global environment:

> parent.env(myenv) <environment: R_GlobalEnv>

The parent environment for the global environment is the empty environment. See help(environment) for details.

Because functions are objects, they also have environments. This is important when considering function closures (functions that are packaged with the state that existed when they were created). Consider a function that is created by another function:

trim <- function(p){ trimit <- function(x){

n <- length(x)

lo <- floor(n*p) + 1

476

CHAPTER 20 Advanced programming

hi <- n + 1 - lo

x <- sort.int(x, partial = unique(c(lo, hi)))[lo:hi]

}

trimit

}

The trim(p) function returns a function that trims p percent of the high and low values from a vector:

>x <- 1:10

>trim10pct <- trim(.1)

>y <- trim10pct(x)

>y

[1] 2 3 4 5 6 7 8 9

>trim20pct <- trim(.2)

>y <- trim20pct(x)

>y

[1]3 4 5 6 7 8

This works because the value of p is in the environment of the trimit() function and is saved with the function:

> ls(environment(trim10pct)) [1] "p" "trimit"

> get("p", env=environment(trim10pct)) [1] 0.1

The lesson here is that, in R, functions include the objects that existed in their environment when they were created. This fact helps to explain the following behavior:

> makeFunction <- function(k){

f<- function(x){ print(x + k)

}

}

>g <- makeFunction(10)

>g (4)

[1] 14

>k <- 2

>g (5) [1] 15

The g() function uses k=3 no matter what value k has in the global environment, because k equaled 3 when the function was created. Again, you can see this with

>ls(environment(g)) [1] "f" "k"

>environment(g)$k [1] 10

In general, the value of an object is obtained from its local environment. If the object isn’t found in its local environment, R searches in the parent environment, then the parent’s parent environment, and so on, until the object is found. If R reaches the empty environment and still hasn’t found the object, it throws an error. This is called lexical scoping.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]