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. This is lesson 4 of 4. Any 3 lessons of this learning path are free to read in full — after that, CoddyKit PRO unlocks every lesson, plus hands-on practice with a built-in code editor and a 24/7 AI tutor. It is part of the R Academy learning path, and your progress syncs across the web and the CoddyKit app. The R Academy course includes 4 lessons in total.
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 999Quick 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=TRUEfor large storesassign('x', v, envir=e)andget('x', envir=e)for programmatic accesse$xande[['x']]work like list accessorsls(envir=e)lists names;exists('x', envir=e, inherits=FALSE)for strict checkas.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')Learn R with an AI tutor — free
Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.
- Courses
- 43
- Lessons
- 159
Frequently Asked Questions
Is the “Creating and Inspecting Environments” lesson free?
Yes — any 3 lessons of the R Academy learning path, including “Creating and Inspecting Environments”, are free to read in full here on the web. After that, CoddyKit PRO unlocks every lesson, plus interactive practice with a built-in code editor and a 24/7 AI tutor. The R Academy course includes 4 lessons in total.
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, so you can start here or from the beginning and move at your own pace. This is lesson 4 of 4.
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
- What Is an Environment in R?
- Lexical Scoping Rules
- Global vs Local Scope
- Creating and Inspecting Environments