0Pricing
R Academy · Lesson

Creating and Inspecting Environments

Use new.env(), environment(), ls(), and get() to work with environments.

Creating and Inspecting Environments is a free R Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the R Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Creating a New Environment

new.env(parent = e) creates a new empty environment. The parent argument sets which environment is searched when a name is not found in the new one. Use emptyenv() for a fully isolated environment.

# Isolated environment (no parent chain)
e1 <- new.env(parent = emptyenv())
# Environment with global as parent
e2 <- new.env(parent = globalenv())
cat('e1 parent:', environmentName(parent.env(e1)), '\n')
cat('e2 parent:', environmentName(parent.env(e2)), '\n')

assign() — Add Bindings

assign('name', value, envir = e) creates or updates a named binding in the specified environment. It is the programmatic equivalent of e$name <- value, but works when the name is stored in a variable.

e <- new.env(parent = emptyenv())
assign('x', 10, envir = e)
assign('y', 'hello', envir = e)
assign('z', TRUE, envir = e)
cat('x:', get('x', envir = e), '\n')
cat('y:', get('y', envir = e), '\n')

get() and mget()

get('name', envir = e) retrieves a single binding. mget(c('a','b'), envir = e) retrieves multiple bindings at once, returning a named list. Both throw an error if the name does not exist (unless inherits allows chain searching).

e <- new.env(parent = emptyenv())
e$alpha <- 1
e$beta  <- 2
e$gamma <- 3
# Single
get('alpha', envir = e)
# Multiple
mget(c('alpha', 'beta', 'gamma'), envir = e)

ls() — List Bindings

ls(envir = e) returns a character vector of all names bound in environment e. Add all.names = TRUE to include names starting with . (hidden by default). The names are returned in alphabetical order.

e <- new.env(parent = emptyenv())
e$b_val  <- 2
e$a_val  <- 1
e$.secret <- 'hidden'
cat('Default ls:', ls(envir = e), '\n')
cat('All names :', ls(envir = e, all.names = TRUE), '\n')

exists() with inherits

exists('name', envir = e, inherits = FALSE) checks only the specified environment, not its parents. With inherits = TRUE (default), it also searches the parent chain. Use inherits = FALSE for strict local checks.

parent_e <- new.env(parent = emptyenv())
parent_e$shared <- 42
child_e  <- new.env(parent = parent_e)
# inherits=TRUE: finds shared in parent
cat('inherits TRUE:', exists('shared', envir = child_e, inherits = TRUE),  '\n')
# inherits=FALSE: only looks in child
cat('inherits FALSE:', exists('shared', envir = child_e, inherits = FALSE), '\n')

environmentName() and parent.env()

environmentName(e) returns the name of a built-in environment ('R_GlobalEnv', 'package:base', etc.). User-created environments return ''. parent.env(e) returns the parent environment object.

e <- new.env(parent = globalenv())
cat('Name of e     :', environmentName(e), '\n')
cat('Parent of e   :', environmentName(parent.env(e)), '\n')
cat('Name of global:', environmentName(globalenv()), '\n')

$ Syntax for Environments

Environments support the $ and [[ syntax like lists for reading and writing bindings. This is often more convenient than get()/assign() for direct access when the name is known at write time.

e <- new.env(parent = emptyenv())
e$pi_approx <- 3.14159
e[['e_approx']] <- 2.71828
cat('pi:', e$pi_approx, '\n')
cat('e :', e[['e_approx']], '\n')

rm() in a Specific Environment

rm('name', envir = e) removes a binding from a specific environment. This is different from removing a global variable — you must specify the environment explicitly when working with custom environments.

e <- new.env(parent = emptyenv())
e$keep <- 1
e$remove_me <- 99
cat('Before:', ls(envir = e), '\n')
rm('remove_me', envir = e)
cat('After :', ls(envir = e), '\n')

as.list() to Dump an Environment

as.list(e) converts all bindings in an environment to a named list, making it easy to inspect or serialize the contents. The result is a snapshot — later changes to the environment are not reflected in the list.

e <- new.env(parent = emptyenv())
e$x <- 10
e$y <- 20
e$z <- 30
bindings <- as.list(e)
cat('Class:', class(bindings), '\n')
cat('Length:', length(bindings), '\n')
str(bindings)

Environments as Hash Tables

The hash = TRUE option in new.env() (default when parent is set) enables hash-based lookup, making name lookup O(1). This makes large environments much faster than lists for key-value storage.

# Build a small key-value store
store <- new.env(hash = TRUE, parent = emptyenv())
keys   <- paste0('key_', 1:5)
values <- c(10, 20, 30, 40, 50)
for (i in seq_along(keys)) assign(keys[i], values[i], envir = store)
# Retrieve
cat('key_3 =', get('key_3', envir = store), '\n')
cat('All keys:', ls(store), '\n')

Copying vs Sharing Environments

Assigning an environment to a new variable does not copy it — both variables reference the same object. Use as.list() then list2env() to make a true copy if you need independent environments.

e1 <- new.env(parent = emptyenv())
e1$val <- 100
e2 <- e1          # reference, not a copy
e2$val <- 999
cat('e1$val:', e1$val, '\n')  # 999, modified via e2!

# True copy:
e3 <- list2env(as.list(e1), parent = emptyenv())
e3$val <- 0
cat('e1$val after e3 change:', e1$val, '\n')  # still 999

Quick Check

Which function checks if a name is bound in an environment without searching its parent environments?

Creating Environments: Key Takeaways

Key takeaways for creating and inspecting environments:

  • new.env(parent=e) creates a new empty environment; hash=TRUE for large stores
  • assign('x', v, envir=e) and get('x', envir=e) for programmatic access
  • e$x and e[['x']] work like list accessors
  • ls(envir=e) lists names; exists('x', envir=e, inherits=FALSE) for strict check
  • as.list(e) dumps to a list; list2env() reconstructs
  • Environments are reference objects — assignment shares, not copies
config <- new.env(hash = TRUE, parent = emptyenv())
assign('host', 'localhost', envir = config)
assign('port', 5432L,       envir = config)
assign('db',   'mydb',      envir = config)
cat('Keys  :', ls(config), '\n')
cat('host  :', config$host, '\n')
cat('port  :', config$port, '\n')

Frequently asked questions

Is the “Creating and Inspecting Environments” lesson free?

Yes — the full text of “Creating and Inspecting Environments” is free to read here on the web, and the R Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the R Academy course, upgrade to CoddyKit PRO.

What will I learn in “Creating and Inspecting Environments”?

Use new.env(), environment(), ls(), and get() to work with environments. You practise R Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start R Academy?

No prior experience is required. R Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Creating and Inspecting Environments” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this R Academy lesson?

Yes. Every R Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. What Is an Environment in R?
  2. Lexical Scoping Rules
  3. Global vs Local Scope
  4. Creating and Inspecting Environments
← Back to R Academy