0

Just to clarify, I'm not saying that R has issues. The problem is probably on my side, but I'm really confused. I have a function (make_a()) that creates a function a(). I also have a function that uses this function in its definition (fun_using_a()):

make_a <- function(x) {
  a <- function(y) {
   x + y
  }
  a
}

fun_using_a <- function(x) {
  a(x)/2
}

Now, I create another function that uses these two:

my_fun <- function(x) {
  a <- make_a(1)
  fun_using_a(x)
}

Calling my_fun(10) gives an error:

my_fun(10)

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

However, everything works fine if do essentially the same thing in the global environment:

a <- make_a(1)
fun_using_a(10)

[1] 5.5

What's going on here? Why does my_fun(10) throw an error? It seems that my understanding of R environments must be a bit off somewhere, but I just can't figure it out. When I call my_fun(), shouldn't the function a() be defined in the execution environment after the first line and thus fun_using_a() should be able to find it there (due to lazy evaluation)?

Any help will be greatly appreciated. Thanks a lot!

apprentice
  • 103
  • 2
  • 1
    The behavior is expected. If R doesn't find an object in the local environment, it looks in the enclosing environment, i.e., the environment where the function was originally created. See https://stackoverflow.com/a/44441912/1315472 and http://adv-r.had.co.nz/Environments.html. – Nairolf Dec 02 '18 at 06:12

1 Answers1

1

You would need to save the result of make_a with name a in a place where fun_using_a can see it. There isn't a single "execution environment", every function invocation creates a new one. As posted, make_a returns a function, but you didn't show it being saved anywhere until your second version of the code.

By the way, make_a is likely to have a subtle bug: since x is never evaluated until the first call to a(), its value could change. For example,

x <- 1
a <- make_a(x)
x <- 5
fun_using_a(10)

will return 7.5, not 5.5, since the value of x in a(y) will be 5 instead of 1. To fix it, force the value of x in make_a:

make_a_2 <- function(x) {
  force(x)
  a <- function(y) {
   x + y
  }
  a
}
user2554330
  • 37,248
  • 4
  • 43
  • 90