Examples for 'rlang::list2'


Collect dynamic dots in a list

Aliases: list2 ll dots_list

Keywords:

### ** Examples

# Let's create a function that takes a variable number of arguments:
numeric <- function(...) {
  dots <- list2(...)
  num <- as.numeric(dots)
  set_names(num, names(dots))
}
numeric(1, 2, 3)
[1] 1 2 3
# The main difference with list(...) is that list2(...) enables
# the `!!!` syntax to splice lists:
x <- list(2, 3)
numeric(1, !!! x, 4)
[1] 1 2 3 4
# As well as unquoting of names:
nm <- "yup!"
numeric(!!nm := 1)
yup! 
   1 
# One useful application of splicing is to work around exact and
# partial matching of arguments. Let's create a function taking
# named arguments and dots:
fn <- function(data, ...) {
  list2(...)
}

# You normally cannot pass an argument named `data` through the dots
# as it will match `fn`'s `data` argument. The splicing syntax
# provides a workaround:
fn("wrong!", data = letters)  # exact matching of `data`
[[1]]
[1] "wrong!"
fn("wrong!", dat = letters)   # partial matching of `data`
[[1]]
[1] "wrong!"
fn(some_data, !!!list(data = letters))  # no matching
$data
 [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s"
[20] "t" "u" "v" "w" "x" "y" "z"
# Empty trailing arguments are allowed:
list2(1, )
[[1]]
[1] 1
# But non-trailing empty arguments cause an error:
try(list2(1, , ))
Error in list2(1, , ) : Argument 2 can't be empty.
# Use the more configurable `dots_list()` function to preserve all
# empty arguments:
list3 <- function(...) dots_list(..., .preserve_empty = TRUE)

# Note how the last empty argument is still ignored because
# `.ignore_empty` defaults to "trailing":
list3(1, , )
[[1]]
[1] 1

[[2]]
# The list with preserved empty arguments is equivalent to:
list(1, missing_arg())
[[1]]
[1] 1

[[2]]
# Arguments with duplicated names are kept by default:
list2(a = 1, a = 2, b = 3, b = 4, 5, 6)
$a
[1] 1

$a
[1] 2

$b
[1] 3

$b
[1] 4

[[5]]
[1] 5

[[6]]
[1] 6
# Use the `.homonyms` argument to keep only the first of these:
dots_list(a = 1, a = 2, b = 3, b = 4, 5, 6, .homonyms = "first")
$a
[1] 1

$b
[1] 3

[[3]]
[1] 5

[[4]]
[1] 6
# Or the last:
dots_list(a = 1, a = 2, b = 3, b = 4, 5, 6, .homonyms = "last")
$a
[1] 2

$b
[1] 4

[[3]]
[1] 5

[[4]]
[1] 6
# Or raise an informative error:
try(dots_list(a = 1, a = 2, b = 3, b = 4, 5, 6, .homonyms = "error"))
Error in eval(expr, envir) : Arguments in `...` must have unique names.
✖ Multiple arguments named `a` at positions 1 and 2.
✖ Multiple arguments named `b` at positions 3 and 4.
# dots_list() can be configured to warn when a `<-` call is
# detected:
my_list <- function(...) dots_list(..., .check_assign = TRUE)
my_list(a <- 1)
Warning: Using `<-` as argument is often a mistake.
Do you need to use `=` to match an argument?

If you really want to use `<-`, please wrap in braces:

  # Bad:
  fn(a <- 1)

  # Good:
  fn(a = 1)       # Match 1 to parameter `a`
  fn({ a <- 1 })  # Assign 1 to variable `a`
[[1]]
[1] 1
# There is no warning if the assignment is wrapped in braces.
# This requires users to be explicit about their intent:
my_list({ a <- 1 })
[[1]]
[1] 1

[Package rlang version 1.1.4 Index]