R을 비롯한 프로그래밍 언어에서는 값들에 이름을 붙인다. 그런데 이름들이 서로 겹치면 곤란하기 때문에 이름공간(namespace)이라는 것을 두어 각각의 이름은 자기 이름 공간 안에서만 유효하도록 한다. R에는 두 종류의 이름 공간이 있는데 하나는 환경(environment)이고 또 하나는 패키지(package)다.
환경 안에 있는 함수는 기본적으로 같은 환경 안에 있는 값이나 함수들을 다룰 수 있다. 다음 예를 보자.
> a <- 1 > f <- function() a <- 2 > f() > a 1
분명히 함수 f를 이용해서 a를 2로 설정해주었지만 a의 값은 여전히 1이다. 왜냐하면 두 a는 다른 환경에 있기 때문이다. 함수 내부는 독립적인 환경이기 때문에 그 바깥(전역 환경 global environment)에 있는 이름을 불러서 사용할 수는 있지만 외부 환경에 있는 이름의 내용을 바꿀 수는 없도록 되어있다.
전역환경의 이름을 바구려면 <- 대신 <<-을 쓰면 된다. <<-는 현재 환경을 포함하는 환경들을 거슬러 올라가면서 해당하는 이름을 찾아 값을 바꾼다.
> a <- 1 > f <- function() a <<- 2 > f() > a 2
환경은 리스트와 똑같은 방법으로 쓸 수 있다. 전역환경을 가리키는 이름은 .GlobalEnv다.
> a <- 1 > f <- function() .GlobalEnv$a <- 2 > f() > a 2
환경, 리스트, 데이터프레임은 모두 $를 사용해서 그 안에 있는 값들을 다룰 수 있다. 이 모두를 그냥 리스트로 보아도 무관하다. 만약 특정한 환경에 있는 이름들을 전역환경에 있는 이름처럼 쓰려면 attach 함수를 쓰면 된다. 이것을 취소하려면 detach를 쓴다.
> rm(x) > e <- new.env() > e$x <- 1 > x Error:object "x" not found
new.env 함수로 e라는 새로운 환경을 만들었다. 아직 x는 전역 환경에서 접근할 수 없다.
> attach(e) > x [1] 1 > x <- 2 > x [1] 2 > detach(e) > x [1] 2 > e$x [1] 1
attach 함수를 이용하면 환경 e에 있는 이름을 쓸 수 있다. 그런데 <-를 쓰면 함수 안에서와 마찬가지로 환경 e에 있는 내용을 바꾸는 게 아니고 전역 환경에 새로운 x를 만든다.
> rm(x) > attach(e) > x [1] 1 > x <<- 3 > x [1] 3 > detach(e) > x Error:object "x" not found > e$x [1] 1
<<-를 쓰면 어떨까? attach 함수를 사용하면 현재 환경과 다른 환경을 합친 새로운 환경 속으로 들어가게 된다. <<-는 이 새로운 환경에 있는 이름을 바꾸게 된다. 그래서 detach를 하고나면 <<-에 의해 할당된 값은 사라진다.
패키지는 또 다른 종류의 이름 공간이다. 환경에 있는 이름을 쓸 때 $를 쓰듯이 패키지에 있는 이름은 ::나 :::를 사용한다. 패키지를 불러들이면 자동으로 패키지에 있는 이름들이 attach 되기 때문에 ::나 :::를 직접 쓸 일은 없다.
하지만 여러 개의 패키지를 쓰다보면 똑같은 이름이 있을 수가 있다. 이미 전역환경에 있는 것과 같은 이름이 패키지에 있을 때 아래와 같은 메시지가 뜬다.
The following object(s) are masked _by_ .GlobalEnv :
이렇게 masked 된 경우에는 먼저 있던 이름이 가리고 있는 것 뿐이므로 rm으로 그것을 지워주면 쓸 수 있게 된다. 그러나 두 가지 이름을 모두 써야할 경우에는 명시적으로 ::을 쓴다. 예를 들어 MASS 패키지의 area 함수라면 MASS::area와 같은 형태로 쓴다.
패키지에 있는 모든 이름을 전역 환경에서도 쓸 수 있는 것은 아니다. 일부 이름들은 패키지 외부에서는 쓸 필요가 있기 때문에 전역 환경에서 바로 쓸 수 없다. :::는 이런 이름들에 접근할 때 쓰는 데 웬만하면 쓸 일도 없고 가능하면 쓰지 않는 것이 바람직하다.