ruser-defined-functionsfunction-composition

Function to add a command line to an existing function


I need to write a function to add a particular command/string of characters to an existing function.

Consider this function:

constraint = function(cov_matrix,max_variance){ 

function(x){
f = NULL 
g = NULL 
g = rbind(g,  t(x)%*%cov_matrix%*%x-max_variance) 
return(list(ceq = f, c= g)) 
} 
}

Ideally, I would like to write a function add_text() that would take as input ("some_text_or_command", constraint) that would generate the output.

constraint = function(cov_matrix, max_variance){ 

function(x){
f = NULL 
g = NULL 
g = rbind(g,  t(x)%*%cov_matrix%*%x-  max_variance) 
"some_text_or_command"
return(list(ceq = f, c= g)) 
} 

}

How to go about it?


Solution

  • Here's how to do it, except for one crucial step:

    add_text <- function(addition, original) {
      body <- body(original)
    
      # the missing step:  figure out the path to the line before where you're putting
      # the addition, i.e. the line 
      #   g = rbind(g,  t(x)%*%cov_matrix%*%x-  max_variance) ` 
      # in your example.  The path in your example is `c(2,3,4)`, so
      # I'll use that.
    
      prev_line <- c(2,3,4)
    
      len <- length(prev_line)   # How deeply nested is that line?
    
      # Now the edits:
    
      if (len > 1)   # Is that line nested?  It usually is, but not always
        parent <- body[[prev_line[-len]]]
      else
        parent <- body
    
      insert_at <- prev_line[len]
      
      parent <- as.list(parent)
      parent <- append(parent, list(substitute(addition)), after = insert_at)
      parent <- as.call(parent)
      if (len > 1)
        body[[prev_line[-len]]] <- parent
      else 
        body <- parent
    
      body(original) <- body
      original
    }
    
    

    For example,

    add_text(1 + 1, constraint)
    

    will give the function

    function (cov_matrix, max_variance) 
    {
        function(x) {
            f = NULL
            g = NULL
            g = rbind(g, t(x) %*% cov_matrix %*% x - max_variance)
            1 + 1
            return(list(ceq = f, c = g))
        }
    }