Using functions and environments

后端 未结 3 2182
星月不相逢
星月不相逢 2020-12-09 13:52

Following the recent discussions here (e.g. 1, 2 ) I am now using environments in some of my code. My question is, how do I create functions that modify environments accordi

相关标签:
3条回答
  • 2020-12-09 14:30

    You only need to make one change to make your example work - redefine your function to use substitute() to 'fix' the desired values within the scope of f():

    f <- function(env,z) {
        eval(substitute(x+z,list(z=z)), env)
    }
    

    This can quickly get murky especially since you can even include assignment statements within substitute() (for instance, replace x+z with y <- x+z, not that this is entirely relevant here) but that choice can be made by the developer...

    Additionally, you can replace list(z=z) in the substitution expression above with environment() (e.g., substitute(x+z,environment())) as long as you don't have conflicting variable names between those passed to f() and those residing in your 'env', but you may not want to take this too far.

    Edit: Here are two other ways, the first of which is only meant to show the flexibility in manipulating environments and the second is more reasonable to actually use.

    1) modify the enclosing environment of 'env' (but change it back to original value before exiting function):

    f <- function(env,z) {
      e <- environment(env)
      environment(env) <- environment()
      output <- with(env,x+z)
      environment(env) <- e
      output
    }
    

    2) Force evaluation of 'z' in current environment of the function (using environment()) rather than letting it remain a free variable after evaluation of the expression, x+z, in 'env'.

    f <- function(env,z) {
      with(environment(),with(env,x+z))
    }
    

    Depending on your desired resolution order, in case of conflicting symbol-value associations - e.g., if you have 'x' defined in both your function environment and the environment you created, 'y' (which value of 'x' do you want it to assume?) - you can instead define the function body to be with(env,with(environment(),x+z)).

    0 讨论(0)
  • 2020-12-09 14:34

    The simplest solution is to use the environment when referencing the object:

    y <- new.env()
    y$x <- 1
    f <- function(env,z) {
        env$x+z
    }
    f(y,z=1)
    

    You would need to assign z to your environment as well.

    y <- new.env()
    with(y, x <- 1)
    f <- function(env,z) {
        assign("z", z, envir=env)
        with(env, x+z)
    }
    f(y,z=1)
    

    One other option would be to attach your environment so that the variables can now be used directly.

    y <- new.env()
    with(y, x <- 1)
    f <- function(env,z) {
        attach(env)
        y <- x + z
        detach(env)
        y
    }
    f(y,z=1)
    

    This latter solution is powerful because it means you can use any object from any attached environment within your new environment, but it also means that you need to be very careful about what has been assigned globally.

    Edit:

    This is interesting, and I don't entirely understand the behavior (i.e. why z is not in the scope of the with call). It has something to do with the creation of the environment originally that is causing it to be outside the scope of the function, because this version works:

    f <- function(z) {
        y <- new.env()
        with(y, x <- 1)
        with(y, x+z)
    }
    f(y,z=1)
    
    0 讨论(0)
  • 2020-12-09 14:47
     y <- new.env()
     with(y, x <- 1)
     f <- function(env,z) {
        with(env, x+z)
     }
     f(y,z=1)
    

    mind the parentheses:) The following will work:

    with(env, x)+z
    
    0 讨论(0)
提交回复
热议问题