Search code examples
rnsenon-standard-evaluation

Iterate over symbols defined in some inner environment using non-standard evaluation


I'd like to make below program work.

I know, the error lies in list(f1, f2), but I didn't find a way to make it work so far. The problem is that f1 and f2 are not known outside func's environment, but I'd like to just pass them as a name / symbol...

x = 1:2
func = function(f,x){
  f1 = function(x) 
    sum(x)
  f2 = function(x) 
    prod(x)
  eval(substitute(f))(x)
}
func(f1, x) # works
func(f2, x) # works
sapply(list(f1,f2), function(f) func(f,x)) # cannot iterate over f's

Solution

  • With this definition f can be a character string naming a function or an unevaluated expression naming a function.

    func <- function(f, x) { 
      funs <- list(f1 = sum, f2 = prod)
      ch <- deparse(substitute(f))
      if (! ch %in% names(funs)) ch <- as.name(f)
      funs[[ch]](x)
    }
    
    
    
    func(f1, 1:2)
    ## [1] 3
    
    func("f1", 1:2)
    ## [1] 3
    
    sapply(c("f1", "f2"), func, x = 1:2)
    ## f1 f2 
    ##  3  2 
    
    sapply(c(quote(f1), quote(f2)), func, x = 1:2)
    ## [1] 3 2
    
    sapply(expression(f1, f2), func, x = 1:2)
    ## [1] 3 2
    

    In a comment under the question, the poster mentioned that they may not use unevaluated expressions after all. If character strings only are used then it could be simplified to this:

    func2 <- function(f, x) { 
      funs <- list(f1 = sum, f2 = prod)
      funs[[f]](x)
    }
    
    func2("f1", 1:2)
    ## [1] 3
    
    sapply(c("f1", "f2"), func2, x = 1:2)
    ## f1 f2 
    ##  3  2 
    

    Updates

    Corrections and improvements.