R中的Lisp/Scheme-like调用

gag*_*ews 8 lisp scheme parsing expression r

出于某些原因,我想以更多的Lisp/Scheme方式使用R调用(至少就语法而言)(我们都知道R 受到了Scheme的大量启发).

因此,我设置了以下功能:

. <- function(f, ...)
   eval(match.call()[-1], envir=parent.frame())
Run Code Online (Sandbox Code Playgroud)

这允许我表达例如以下R代码:

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

在以下语义等效形式中:

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

.(`for`, i, x,
   .(`{`, 
      .(print,
         .(`:`, 1, i))))
Run Code Online (Sandbox Code Playgroud)

我对目前的定义非常满意.(因为它只是为了娱乐而制作).但它肯定远非完美.特别是它的表现当然很差:

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
Run Code Online (Sandbox Code Playgroud)

所以我想知道你是否可以提出一些有关定义的想法.来解决上述问题.欢迎使用C/C++代码.

amo*_*moe 4

正如 Brian Diggs 上面评论的那样,您可以使用它do.call来执行更快的调用,而无需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
Run Code Online (Sandbox Code Playgroud)

我怀疑要获得与裸函数调用相同的性能将需要修改 R 源本身。