1

Basically, I would like to create an R function separate_call that gets an argument like x[ind] and returns x and ind (so, from the parent environment):

x <- 1:10
ind <- 2:3
separate_call(x[ind]) ## should return `list(1:10, 2:3)`

I know that I need to use non-standard evaluation and some tree parsing but I'm not familiar enough with these two concepts. Any help would be appreciated.

F. Privé
  • 11,423
  • 2
  • 27
  • 78
  • Do you want the solution to be literally `list(1:10, 2:3)` as symbol or as a character "list(1:10,2:3)" or `$x [1] 1 2 3 4 5 6 7 8 9 10 $ind [1] 2 3` – PKumar Jun 02 '18 at 06:18
  • The last one (numbers). I found a solution. If you have a better solution, please add it. – F. Privé Jun 02 '18 at 06:18

2 Answers2

2

Looking at the code of pryr:::tree and experimenting a little bit, I found a solution:

separate_call <- function(call) {
  call.sep <- as.list(substitute(call))
  parent_env <- parent.frame()
  x   <- eval(call.sep[[2]], parent_env)
  ind <- eval(call.sep[[3]], parent_env)
  list(x, ind)
}

Verification:

> x <- 1:10
> ind <- 2:3
> separate_call(x[ind])
[[1]]
 [1]  1  2  3  4  5  6  7  8  9 10

[[2]]
[1] 2 3

> separate_call(x[1:2])
[[1]]
 [1]  1  2  3  4  5  6  7  8  9 10

[[2]]
[1] 1 2
F. Privé
  • 11,423
  • 2
  • 27
  • 78
1

I am adding this solution, not very elegant, see if this fits your need.

separate_call <- function(m){
    dprse <- deparse(substitute(m)) ##deparsing the data: to make it as string
    lyst <- strsplit(dprse,"\\[|\\]")[[1]] ##removing the square brackets to sparate contents of m
    lapply(lyst, function(y)eval(parse(text = y), envir = parent.frame()))

}

I hope this works, I tried it by calling it in three different ways

separate_call(1:10[ind])
separate_call(x[2:3])
separate_call(1:10[2:3])

They all gave me same response

> separate_call(1:10[ind])
[[1]]
 [1]  1  2  3  4  5  6  7  8  9 10

[[2]]
[1] 2 3

> separate_call(x[2:3])
[[1]]
 [1]  1  2  3  4  5  6  7  8  9 10

[[2]]
[1] 2 3

> separate_call(1:10[2:3])
[[1]]
 [1]  1  2  3  4  5  6  7  8  9 10

[[2]]
[1] 2 3
PKumar
  • 10,971
  • 6
  • 37
  • 52
  • Unfortunately, `get` won't work if you specify directly `2:3` instead of `ind`. – F. Privé Jun 02 '18 at 06:26
  • You should add the environment to the eval call (imagine you have `lyst <- x; separate_call(lyst[ind])`. In any case, I thing my current solution would be more robust than using regular expressions. – F. Privé Jun 02 '18 at 08:32