Lisp / Schema-like calls in R

For some reason, I would like to play with R-calls (at least in syntax) in a more Lisp / Scheme-like style (we all know that R was strongly inspired by Scheme ).

So I installed the following function:

. <- function(f, ...) eval(match.call()[-1], envir=parent.frame()) 

Which allows me to express, for example. following R code:

 x <- sort(sample(1:10, 5, replace=TRUE)) for (i in x) { print(1:i) } 

in the following semantically equivalent form:

 .(`<-`, x, .(sort, .(sample, .(`:`, 1, 5), 5, replace=TRUE))) .(`for`, i, x, .(`{`, .(print, .(`:`, 1, i)))) 

I am quite pleased with the current definition . (as it was done for pleasure). But he is certainly far from perfect. In particular, its performance is, of course, poor:

 microbenchmark::microbenchmark(1:10, .(`:`, 1, 10)) ## Unit: nanoseconds ## expr min lq median uq max neval ## 1:10 189 212.0 271.5 349 943 100 ## .(`:`, 1, 10) 8809 10134.5 10763.0 11467 44066 100 

So, would you be interested to come up with some ideas regarding the definition . that could solve the above problem. C / C ++ code is welcome.

+7
r expression parsing lisp scheme
source share
1 answer

As Brian Diggs has already pointed out, you can use do.call to make quick calls without the overhead of eval .

 > myfn <- function(f, ...) + do.call(f, list(...), envir=parent.frame()) > myfn(`:`, 1, 10) [1] 1 2 3 4 5 6 7 8 9 10 > microbenchmark::microbenchmark(1:10, .(`:`, 1, 10), myfn(`:`, 1, 10)) Unit: nanoseconds expr min lq median uq max neval 1:10 177 286.0 346.5 404.0 887 100 .(`:`, 1, 10) 9794 11454.0 12141.5 12808.5 48391 100 myfn(`:`, 1, 10) 3504 4413.5 4751.5 5287.5 48227 100 

I suspect that obtaining equivalent performance for a voice call function will require modification of the source R itself.

+4
source share

All Articles