environment()

Updated March 13, 2026 · Data Types
environment data-type r scoping

An environment in R is a data structure that associates (binds) names to objects. Unlike lists, environments have a parent environment that forms a scope chain — when R looks up a name, it searches the current environment first, then walks up the parent chain until it finds the name or reaches the empty environment. This is how R’s lexical scoping works.

Creating Environments

You can create new environments with new.env(). By default, the parent is the current environment (the global environment in interactive use).

# Create a new empty environment
env <- new.env()

# Add variables to it using $ or [[]]
env$x <- 10
env[["y"]] <- "hello"

# Access variables
env$x
# [1] 10

Working with Environments

FunctionDescription
ls(env)List all names in an environment
get("x", envir = env)Retrieve a value by name
assign("x", value, envir = env)Set a value by name
exists("x", envir = env)Check if a name exists
rm("x", envir = env)Remove a binding
parent.env(env)Get the parent environment
environmentName(env)Get the environment’s name
env <- new.env()
env$a <- 1:5
env$b <- "data"

ls(env)
# [1] "a" "b"

exists("a", envir = env)
# [1] TRUE

get("b", envir = env)
# [1] "data"

The Scope Chain

Every environment has a parent. When you use a name, R searches up the chain:

# Create parent environment
parent <- new.env()
parent$shared <- "I'm in parent"

# Create child environment with parent
child <- new.env(parent = parent)
child$local <- "I'm in child"

child$shared
# [1] "I'm in parent"

child$local
# [1] "I'm in child"

Common Patterns

Package Namespaces

Packages use environments to isolate their code. When you load a package with library(), R attaches it to the search path:

# The base environment is at the top of the search path
search()
# [1] ".GlobalEnv"        "package:stats"     
# [3] "package:base"      

# dplyr creates its own environment with its functions
library(dplyr)
ls(where = as.environment("package:dplyr"))[1:5]
# [1] "%>%"       "filter"    "select"    "mutate"    "arrange"

Function Environments

Every function has an associated environment where its free variables are looked up:

make_adder <- function(x) {
  function(y) x + y
}

add5 <- make_adder(5)
environment(add5)
# <environment: 0x558a2b6e8>

# x is stored in the function's enclosing environment
get("x", envir = environment(add5))
# [1] 5

Caching with Environments

Environments are mutable and use reference semantics, making them useful for caching:

cache <- new.env()
compute_expensive <- function(key) {
  if (exists(key, envir = cache)) {
    message("Fetching from cache")
    return(get(key, envir = cache))
  }
  result <- Sys.sleep(1) # simulate expensive computation
  result <- paste0("computed: ", key)
  assign(key, result, envir = cache)
  result
}

compute_expensive("data1")  # Takes ~1 second
# [1] "computed: data1"
compute_expensive("data1")  # Instant (from cache)
# Fetching from cache
# [1] "computed: data1"

See Also