Skip to content
Prev 42823 / 63424 Next

Converting expression to a function

Hi John,

Here's a somewhat streamlined version of the code:

Form2resfun <- function(f, params) {
  stopifnot(inherits(f, "formula"), length(f) == 3)

  # Create function body
  body <- substitute(
    crossprod(rhs - lhs), list(lhs = f[[2]], rhs = f[[3]])
  )

  # Create argument list
  free_params <- setdiff(all.vars(f), names(params))
  missing_args <- setNames(rep(list(bquote()), length(free_params)),
    free_params)
  args <- as.pairlist(c(missing_args, params))

  eval(call("function", args, body))
}

# a test
tfn <- Form2resfun(y ~ b1 / (1 + b2 * exp(-1 * b3 * t)),
  c(b1 = 1, b2 = 1, b3 = 1))

tfn

y <- c(5.308, 7.24, 9.638, 12.866, 17.069, 23.192, 31.443,
     38.558, 50.156, 62.948, 75.995, 91.972)
tfn(y, seq_along(y))


It basically works by generating the call to "function", so you get
back a regular function (although I haven't made sure it has the
environment that you might expect).  A couple of tricks:

* bquote() generates a call that represents a missing value

* using as.pairlist to make sure that the arugments argument to
function is a pairlist - as far as I know this is the only case where
you need to care about the difference between lists and pairlists

You may also want to chat with Randy Pruim, who seems to be working on
similar stuff.

Hadley
On Sun, Mar 18, 2012 at 12:01 PM, John C Nash <nashjc at uottawa.ca> wrote: