For some reasons, I'd like to play with R calls (at least as far as syntax is concerned) in a more Lisp/Scheme-like fashion (we all know that R has been heavily inspired by Scheme).
Thus, I set up the following function:
. <- function(f, ...)
eval(match.call()[-1], envir=parent.frame())
Which allows me to express e.g. the 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'm quite satisfied with the current definition of .
(as it's just made for fun). But it's surely 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 I wonder if you could come up with some ideas concerning the definition of .
that would address the above issue. C/C++ code is welcome.
As Brian Diggs commented above, you can use do.call
to perform faster 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 getting equivalent performance to a bare function call will require modification of the R source itself.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With