Search code examples
rfunctionnon-standard-evaluation

Change the body of a function without quote marks


I need to change the body of a function depending on input given by users.

modelstring <- function() {
  for (h in (l1i1[j]):(l1i2[j])) {
    w[h] <- 1/l1n[h]
  }
}

userinput <- "b.w[1]*X.w[i,1]^exp(b.w[2]*X.w[i,2])"

body(modelstring)[[2]][[4]][[2]][[3]] <- userinput 

The problem is that the changed function includes quotation marks. How do I get rid of them?

modelstring

function () 
{
    for (h in (l1i1[j]):(l1i2[j])) {
        w[h] <- "b.w[1]*X.w[i,1]^exp(b.w[2]*X.w[i,2])"
    }
}

When evaluating the user input as formula, the replacement works and no quotation marks are inserted

userinput <- as.formula(w ~ b.w[1]*X.w[i,1]^exp(b.w[2]*X.w[i,2]))

However, I need to use <- or just the right-hand side. In those cases, the formula is evaluated, which gives an error.

I have also tried noquote which still gives quotation marks:

userinput <- noquote("b.w[1]*X.w[i,1]^exp(b.w[2]*X.w[i,2])")

Finally, I have tried different combinations of expr(!!userinput), subs(), and substitute.


Solution

  • Assuming that the desired inputs are

    1. the modelstring function and
    2. the text of the replacement as a character string, userinput

    use parse to convert the string to an expression and then add [[1]] on the end to convert that from an expression to a call object:

    userinput <- "b.w[1]*X.w[i,1]^exp(b.w[2]*X.w[i,2])" # as in question
    body(modelstring)[[2]][[4]][[2]][[3]] <- parse(text = userinput)[[1]]
    
    modelstring
    ## function () 
    ## {
    ##     for (h in (l1i1[j]):(l1i2[j])) {
    ##         w[h] <- b.w[1] * X.w[i, 1]^exp(b.w[2] * X.w[i, 2])
    ##     }
    ## }
    

    Here is a simpler example that may be useful to play around with:

    # inputs
    f <- function() { 37 }
    s <- "pi * pi"
    
    body(f)[[2]] <- parse(text = s)[[1]]
    f()
    ## [1] 9.869604