1

If I have a string like:

s <- "x = 1"

how do I pass this to list() and end up with a list with one element named "x" and equal to 1. Like this:

list(x = 1)

I tried:


list(eval(str2lang(s)))

I know one way to do this:


s2 <- strsplit(s, " = ")[[1]]

stats::setNames(list(s2[2]), s2[1])

I don't like the above solution, however, because it produces double and singles quotes if the value being assigned inside the list is already quoted:

s <- "x = 'a'"
s2 <- strsplit(s, " = ")[[1]]

lst1 <- stats::setNames(list(s2[2]), s2[1])

lst2 <- list(x = 'a')

all.equal(lst1, lst2)

Update

A number of solutions have been offered, but none seem to do quite what I had in mind when I say "how do I pass [a string] to list()".

This is what I mean:

list(x = 'z', y = 1, some_function("x = 'a'"))

where some_function can take a string, parse the expression inside, and then have it evaluated as if it were just another named object being passed to list().

Giovanni Colitti
  • 1,982
  • 11
  • 24
  • 2
    `eval(str2lang(sprintf('list(%s)',s)))` should work. But why have a string in the first place? – Onyambu Feb 09 '23 at 23:21
  • 1
    Well, I'm considering adding an argument in a config file that determines specific filtering criteria for an entry in the config file, and the argument would a string. But mostly I'm just curious. – Giovanni Colitti Feb 09 '23 at 23:40

2 Answers2

2
f <- function(string){
  a <- str2lang(string)
  as.list(setNames(a[[3]], as.character(a[[2]])))
}

s1 <- "x = 'a'"
s <- "x = 1"

f(s)
#> $x
#> [1] 1
f(s1)
#> $x
#> [1] "a"

Created on 2023-02-09 with reprex v2.0.2

Using eval, you could do:

 eval(str2lang(sprintf('list(%s)',s)))
Onyambu
  • 67,392
  • 3
  • 24
  • 53
  • I think I might even like your commented answer more: `eval(str2lang(sprintf('list(%s)',s)))`, just because it's more concise. But I was really looking for some solution that would go inside like `list(x = 'z', y = 1, some_function("x = 'a'"))`. – Giovanni Colitti Feb 09 '23 at 23:44
  • 2
    @GiovanniColitti the problem you stated in this comment is different from the one you asked. If the comment works, thats fine. Will add it in this solution too. I was trying to avoid the use of `eval` as it has potential downside. – Onyambu Feb 09 '23 at 23:46
  • What is the potential downside of using `eval` here? – Giovanni Colitti Feb 10 '23 at 00:13
  • @GiovanniColitti in this example i do not see any, though in general better avoid evaluating strings. `eval` is better used to evaluate quoted/unevaluated expressions. try reading [this](https://stackoverflow.com/questions/13649979/what-specifically-are-the-dangers-of-evalparse#comment18731187_13649979) – Onyambu Feb 10 '23 at 00:19
1
s = "x = 1"

env <- new.env(parent = emptyenv())
env[["list"]] <- base::list

eval(str2lang(paste0("list(", s, ")")), env)
#> $x
#> [1] 1

The empty env environment is in order to prevent running code other than "list".

Ric
  • 5,362
  • 1
  • 10
  • 23
  • 1
    Similar idea building on what you have - `l <- new.env(); eval(str2lang(s), envir=l); as.list.environment(l)` – thelatemail Feb 10 '23 at 00:39