-1

I am having trouble with drake issue 35, and I have reproduced a minimal version of the bug for this SO post. Briefly, I want eval(parse()) to work with nested functions, nontrivial closures, and a custom environment. I will consider the problem solved if eval(parse(text = "f(1:10)"), envir = e) below returns 2:11 with no errors or warnings.

e = new.env(parent = globalenv())
e$f = Vectorize(function(x) g(x), "x")
e$g = function(x) x + 1
eval(parse(text = "f(1:10)"), envir = e)

Error in (function (x) : could not find function "g"

environment(e$f) = environment(e$g) = e
eval(parse(text = "f(1:10)"), envir = e)

Error in match(x, table, nomatch = 0L) : object 'vectorize.args' not found

EDIT

In the real world, f and g are user-defined, so I should keep the bodies of these functions as-is.

landau
  • 5,636
  • 1
  • 22
  • 50

2 Answers2

2

Use attach to attach the objects of e environment and call the function f.

e = new.env(parent = globalenv())
e$f = Vectorize(function(x) g(x), "x")
e$g = function(x) x + 1
attach(e)
search()
eval(parse(text='f(1:10)'))
# [1]  2  3  4  5  6  7  8  9 10 11
detach(e)
search()
Sathish
  • 12,453
  • 3
  • 41
  • 59
  • I really wish I could do that, but in the real world, `f` and `g` are user-defined. It is an unavoidable part of what `drake` is trying to accomplish. – landau Apr 28 '17 at 17:04
  • It's okay, I did not fully lay out the constraints of the problem. The edit to the OP should help. – landau Apr 28 '17 at 17:06
  • I just mention `drake` because otherwise people will criticize the premise of using `eval(parse())`. – landau Apr 28 '17 at 17:11
  • That looks much more promising, but I am still getting `Error in g(x) : could not find function "g"`. I tried your idea R 3.3.3 and 3.4.0 on Red Hat Linux 4.4.7-16 and R 3.3.3 on Windows 7. – landau Apr 28 '17 at 17:29
  • That's the weird part. I started with a fresh workspace every time. Not even an auto-loaded `.RData` file. – landau Apr 28 '17 at 17:31
  • Aha! That just might work for the package. Thank you! – landau Apr 28 '17 at 17:43
  • Note: it is not best practice to use attach an object or environment. Please use it with caution, because of possible naming collisions – Sathish Apr 28 '17 at 17:44
  • Yes. Fortunately, I only have a single environment to attach, so I should be able to manage. – landau Apr 28 '17 at 17:45
0

For posterity, I just want to add another approach to the same idea that does not rely on attach().

e = new.env(parent = globalenv())
eval(parse(text='f <- Vectorize(function(x) g(x), "x")'), envir = e)
eval(parse(text='g <- function(x) x + 1'), envir = e)
e2 = list2env(as.list(e), parent = e)
eval(parse(text = "f(1:10)"), envir = e2)

[1] 2 3 4 5 6 7 8 9 10 11

landau
  • 5,636
  • 1
  • 22
  • 50