R中更高级别的功能 - 是否有官方撰写操作员或咖喱功能?

Ale*_*own 37 functional-programming r higher-order-functions

我可以在R中创建一个compose运算符:

 `%c%` = function(x,y)function(...)x(y(...)) 
Run Code Online (Sandbox Code Playgroud)

要像这样使用:

 > numericNull = is.null %c% numeric
 > numericNull(myVec)
 [2] TRUE FALSE
Run Code Online (Sandbox Code Playgroud)

但我想知道是否有一套官方功能来完成这类事情以及其他操作,比如在R.中进行currying.这主要是为了减少代码中括号,函数关键字等的数量.

我的咖喱功能:

> curry=function(...){
    z1=z0=substitute(...);z1[1]=call("list");
    function(...){do.call(as.character(z0[[1]]),
                          as.list(c(eval(z1),list(...))))}}
> p = curry(paste(collapse=""))
> p(letters[1:10])
[1] "abcdefghij"
Run Code Online (Sandbox Code Playgroud)

这对于例如聚合来说特别好:

> df = data.frame(l=sample(1:3,10,rep=TRUE), t=letters[1:10])
> aggregate(df$t,df["l"],curry(paste(collapse="")) %c% toupper)
  l    x
1 1  ADG
2 2  BCH
3 3 EFIJ
Run Code Online (Sandbox Code Playgroud)

我发现它比以下更优雅和可编辑:

> aggregate(df$t, df["l"], function(x)paste(collapse="",toupper(x)))
  l    x
1 1  ADG
2 2  BCH
3 3 EFIJ
Run Code Online (Sandbox Code Playgroud)

基本上我想知道 - 这已经为R做过吗?

Sha*_*ane 28

这两个函数实际上都存在于Peter Danenberg roxygen包中(参见此处的源代码)(最初基于Byron Ellis的R-Help解决方案):

Curry <- function(FUN,...) {
  .orig = list(...);
  function(...) do.call(FUN,c(.orig,list(...)))
}

Compose <- function(...) {
  fs <- list(...)
  function(...) Reduce(function(x, f) f(x),
                       fs,
                       ...)
}
Run Code Online (Sandbox Code Playgroud)

注意Reduce函数的用法,这在尝试用R进行函数式编程时非常有用.请参阅?Reduce以获取更多细节(其中还包括其他函数,如MapFilter).

你的Curry的例子(在这个用法上略有不同):

> library(roxygen)
> p <- Curry(paste, collapse="")
> p(letters[1:10])
[1] "abcdefghij"
Run Code Online (Sandbox Code Playgroud)

这是一个展示Compose(将三个不同的函数应用于字母)的实用程序的示例:

> Compose(function(x) x[length(x):1], Curry(paste, collapse=""), toupper)(letters)
[1] "ZYXWVUTSRQPONMLKJIHGFEDCBA"
Run Code Online (Sandbox Code Playgroud)

你的最后一个例子就是这样的:

> aggregate(df[,"t"], df["l"], Compose(Curry(paste, collapse=""), toupper))
  l    x
1 1  ABG
2 2 DEFH
3 3  CIJ
Run Code Online (Sandbox Code Playgroud)

最后,这是一种做同样事情的方法plyr(也可以很容易地完成byaggregate已经显示):

> library(plyr)
> ddply(df, .(l), function(df) paste(toupper(df[,"t"]), collapse=""))
  l   V1
1 1  ABG
2 2 DEFH
3 3  CIJ
Run Code Online (Sandbox Code Playgroud)

  • 前一段时间,FWIW,`Compose`和`Curry`被移到了`functional`包中. (9认同)
  • 使用软件包进行函数式编程的文字编程是不是有问题?这对于R libs的模块化有何意义? (2认同)

elv*_*o79 6

R中函数式编程的标准位置现在是functional库.

从图书馆:

功能:Curry,Compose和其他高阶函数

例:

   library(functional)
   newfunc <- Curry(oldfunc,x=5)
Run Code Online (Sandbox Code Playgroud)

CRAN:https://cran.r-project.org/web/packages/functional/index.html

PS:这个库替代了ROxigen库.