Search code examples
rlistfunctionoptimization

Optimal way to declare a function F to select from a nested set of functions L


I have a set of model equations that i want to group inside a function to call them as required. As an example of desired workflow, it should be as this call:

F(X=t, mode="B")

I have thought over other ways to declare this kind of process:

t <- seq(0,1,.1)
L <- list(
    A = function(x) x^2, 
    B = function(x) x/(x+9), 
    C = function(x) x*exp(x))
F <- L$A(t)
F
 > 0 .01 .04 .09 .016 .025 .036 .049 .064 .081 1

Also, this task could be done with external packages:

t <- seq(0,1,.1)
F <- function(input, mode){
    dplyr::case_when(
        mode == "A" ~ input^2, 
        mode == "B" ~ input/(input+9),
        mode == "C" ~ input*exp(input)
    )
}
F(t, mode="A")
 > 0 .01 .04 .09 .016 .025 .036 .049 .064 .081 1

Thus, in terms of efficiency, is it better to create a reference for this equations inside the global F function and call them as a list or is better to save a external list and load it as a parameter?


Solution

  • The question asks about a matter of efficiency, the answer below is about a convenient way of calling a function from a list of functions.
    You can have a function factory return a function that will dynamically select the wanted function from the list and apply it to its argument.

    t <- seq(0, 1, 0.1)
    L <- list(
      A = function(x) x^2, 
      B = function(x) x/(x+9), 
      C = function(x) x*exp(x))
    
    makeFun <- function(F_List) {
      f <- function(X, mode) F_List[[mode]](X)
      f
    }
    
    # create the function with the function factory
    f <- makeFun(L)
    
    # see if it works
    f(X = t, mode = "A")
    #>  [1] 0.00 0.01 0.04 0.09 0.16 0.25 0.36 0.49 0.64 0.81 1.00
    f(X = t, mode = "B")
    #>  [1] 0.00000000 0.01098901 0.02173913 0.03225806 0.04255319 0.05263158
    #>  [7] 0.06250000 0.07216495 0.08163265 0.09090909 0.10000000
    f(X = t, mode = "C")
    #>  [1] 0.0000000 0.1105171 0.2442806 0.4049576 0.5967299 0.8243606 1.0932713
    #>  [8] 1.4096269 1.7804327 2.2136428 2.7182818
    

    Created on 2024-06-05 with reprex v2.1.0

    The function factory can be a one-liner, just return 'function(etc)' without assigning the result to 'f'.

    makeFun <- function(F_List) function(X, mode) F_List[[mode]](X)