0

Problem: I need a function which takes only one argument, but needs access to some other variables. I don't want to store these in the .GlobalEnv.

Current Solution: Use a function which takes all needed arguments, that create another function which adapt the environment.

Example:

library(rlang)
foo <- function(a, b){
  bar <- function(c){
    out <- a + b + c
    out
  }
  set_env(bar, get_env())
  bar
}
bar <- foo(1, 2)
bar(3)

I strongly believe that this approach have downsides, but I can't put my finger on what these downsides might be. I would be happy if you could help me.

AaronP
  • 185
  • 10
  • 1
    Your example doesn't really require setting the environment at all, so perhaps you could be a bit clearer about why you need to do this? See: foo1 <- function(a, b) {function(c) {a + b + c}};bar1 <- foo(1, 2);bar1(3) – Mike Stanley Sep 22 '17 at 09:47
  • Now that it's simplified to this little example I see that it's just nonsense. Thank you for clarification. – AaronP Sep 22 '17 at 10:20
  • Is there a way that you can rephrase the example to show what you're really trying to do? I'm interested to find out why you've found it necessary. It's a useful philosophical discussion about changing environments like that, and it's a shame to have missed the opportunity. – Mike Stanley Sep 22 '17 at 11:37
  • My current problem is actually solved, but I'm still interested to hear some opinions about the broader concept of changing the environment of a function (for example to the environment of the caller or some package). Should I edit this one or ask another question? – AaronP Sep 22 '17 at 13:06
  • Since you accepted an answer to this question, I'd ask another. – Mike Stanley Sep 22 '17 at 13:49

1 Answers1

1

There's nothing wrong with this. You don't need rlang either:

foo <- function(a, b)
{
    function(c) a + b + c
}

bar <- foo(1, 2)
bar(3)

The returned value of foo will be another function, whose environment is the one in which it was defined. That happens to be foo's environment.

The only time this might be an issue is if there are other objects in foo that interfere with how things should work. To guard against this, you can explicitly create a new environment that is distinct from foo's environment:

foo <- function(a, b)
{
    bar <- function(c) a + b + c
    environment(bar) <- new.env(parent=globalenv())
    bar
}

but this should rarely, if ever, be necessary.

Hong Ooi
  • 56,353
  • 13
  • 134
  • 187