Search code examples
rlisteval

Storing functions in an R list


I'm trying to build a shiny app to help with a decision analysis. In part of the app, the user is required to enter their utility function as text, which R/shiny will convert to an expression. Suppose the user has three parts to their utility functions which will be combined into a larger utility function. The problem I have is defining the list elements in a for loop:

utility.fns <- list()

ufs <- list() ## user input

## each ufs is specified by the user

ufs[[1]] <- "x+1"
ufs[[2]] <- "sin(x)"
ufs[[3]] <- "cos(x)^2"


for(i in 1:3){

  ## turn the text into functions

  utility.fns[[i]] <- function(x){
   eval( parse(text = ufs[[i]]) )
  }
}



utility.fns[[1]](1) ## returns cos(1)^2 ?

The weird thing is that the list utility.fns always returns utility.fns[[3]], regardless of the index. However, manually overriding

> utility.fns[[1]] <- function(x){
+   eval( parse(text = ufs[[1]]) )
+ }
> utility.fns[[1]](1)
[1] 2

fixes the issue. Obviously I can't manually override every time!


Solution

  • The reason why it always returns utility.fns[[3]] is because if you check utility.fns

    utility.fns[[1]]
    
    #function(x){
    #    eval( parse(text = ufs[[i]]) )
    #}
    #<bytecode: 0x1223d31c8>
    

    The i in for loop ended at 3 so it invokes ufs[[3]] always.

    You could keep functions in ufs itself assign the value to x and then use eval, parse

    x <- 1
    eval(parse(text = ufs[[1]]))
    #[1] 2
    eval(parse(text = ufs[[2]]))
    #[1] 0.841
    eval(parse(text = ufs[[3]]))
    #[1] 0.292