Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion Functions.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -1277,7 +1277,11 @@ x <- `names<-`(`*tmp*`, `[<-`(names(`*tmp*`), 2, "two"))
rm(`*tmp*`)
```

(Yes, it really does create a local variable named `*tmp*`, which is removed afterwards.)
(Yes, it really does create a local variable named `*tmp*`, which is removed afterwards.)[^subassignment]

[^subassignment]: See [this StackOverflow answer](https://stackoverflow.com/a/10491881/946850) for an alternative explanation. At the time of writing, even [the R language definition](https://cran.r-project.org/doc/manuals/R-lang.html#Subset-assignment) isn't really specific about why it is necessary to use a temporary local variable, or how exactly complex assignment works with three or more levels. See <https://rpubs.com/krlmlr/telescope> for an example that attempts to shed light on what happens under the hood.

Note the use of `[<-`, which is the replacement variant of a special form introduced below.

### Special forms
\index{special forms}
Expand All @@ -1292,6 +1296,13 @@ The subsetting operators:

* `x[i]` (`` `[`(x, i) ``)
* `x[[i]]` (`` `[[`(x, i) ``)
* `x$a` (`` `$`(x, "a") ``)

The subassignment operators (a combination of the special and replacement forms):

* `x[i] <- value` (`` x <- `[<-`(x, i, value) ``)
* `x[[i]] <- value` (`` x <- `[[<-`(x, i, value) ``)
* `x$a <- value` (`` x <- `$<-`(x, "a", value) ``)

And the tools of control flow:

Expand Down
2 changes: 2 additions & 0 deletions Subsetting.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,8 @@ x[c(1, 2)] <- c(101, 102)
x
```

This looks like `x` is updated in place, but a copy of `x` is created via the copy-on-modify rules (see Section \@ref(copy-on-modify)) if it is bound to more than one name. Section \@ref(replacement-functions) describes the details of complex assignments of the form `x[i1][i2] <- value`.

I recommend that you should make sure that `length(value)` is the same as `length(x[i])`, and that `i` is unique. This is because, while R will recycle if needed, those rules are complex (particularly if `i` contains missing or duplicated values) and may cause problems.

With lists, you can use `x[[i]] <- NULL` to remove a component. To add a literal `NULL`, use `x[i] <- list(NULL)`:
Expand Down