Deep thoughts and gists
by Paweł Piątkowski

Unusual application of eval()

Today I came across a problem when writing a Shiny application: I wanted to dynamically create download handlers, each one with a content function based on the input data. It seemed easy at first:

for (handlerData in allHandlers) {
  output[[paste0("handler_", handlerData)]] = downloadHandler(
    filename = paste0("something", handlerData),
    content = function(file) {
      someFunction(param = handlerData)
    }
  )
}

But something wasn’t right. I got a bunch of identical handlers. A short investigation and it became clear to me that I’d violated one of the essential rules of R.

Now what?

The great heritage of Lisp came to my rescue. I couldn’t use variable’s value in an ad-hoc function definition… but I could paste it into a character string holding the definition of that function!

for (handlerData in allHandlers) {
  functionString = sprintf(
    'function(file) { someFunction(param = "%s") }', handlerData
  )
  downloadHandlerParams = list(
    filename = paste0("something", handlerData),
    content = eval(parse(text = functionString))
  )
  output[[paste0("handler_", handlerData)]] = do.call(
    "downloadHandler", downloadHandlerParams
  )
}

[UPDATE]

The above solution is inelegant as crap; here’s a better one:

for (handlerData in allHandlers) {
  handlerFunction = substitute(
    function(file) { someFunction(param = handlerParam) },
	alist(handlerParam = handlerData)
  )
  downloadHandlerParams = list(
    filename = paste0("something", handlerData),
    content = eval(handlerFunction)
  )
  output[[paste0("handler_", handlerData)]] = do.call(
    "downloadHandler", downloadHandlerParams
  )
}