Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R - How to create a function that accepts a code block as parameter?

Tags:

r

I would like to create a function that accepts a code block as a parameter. I am not sure how to do this in R. I would like to create a function that has similar behavior to the built-in within function.

data <- within(data, {
  var4 <- var2 + var3
  var5 <- var1 / var2
})

I am having trouble finding the within function definition within the R source code. Otherwise, I would probably have my answer.

Thanks

like image 772
Nick Allen Avatar asked Aug 14 '13 12:08

Nick Allen


2 Answers

It’s very simple:

test <- function(block) {
    cat('before\n')
    rv <- block
    cat('after\n')
    rv
}

and to see how it works:

test_called <- test({
    cat('bar\n')
    'baz'
})

running the latter outputs:

before
bar
after

and test_called has the value 'baz'

this shows that the block only gets evaluated if you do something with it, instead of immediately when being passed.

like image 97
flying sheep Avatar answered Nov 15 '22 05:11

flying sheep


This is what I was looking for. You just pass the code block (aka expression) to the eval() function. See ?eval for more details and variants.

foo <- function(expr) {
   result <- eval(expr)
   return(result)
}

Thanks!

UPDATE: To provide some context around this, I was trying to create a function that would execute a long-running expression and then cache (aka save) the result so that it didn't need to be re-run. Here is a simplified version of what I ended up creating. I am open to suggestions on how to do this better.

cache <- function (cache.name, expr) {

    result <- NULL
    cache.file <- sprintf ("%s/%s.rds", cache.dir, cache.name)

    # has the result already been cached?
    if (file.exists (cache.file)) {
        result <- readRDS(cache.file)

    } else {
        # eval the expression 
        result <- eval(expr)

        # cache the result
        saveRDS (result, cache.file, compress = cache.compress)
    }

    return(result)
}
like image 24
Nick Allen Avatar answered Nov 15 '22 06:11

Nick Allen