R 中的更高级别函数 - 是否有官方的 compose 运算符或 curry 函数?
我可以在 R 中创建一个 compose 运算符:
`%c%` = function(x,y)function(...)x(y(...))
像这样使用:
> numericNull = is.null %c% numeric
> numericNull(myVec)
[2] TRUE FALSE
但我想知道是否有一组官方函数可以执行此类操作以及其他操作,例如 R 中的柯里化。很大程度上,这是为了减少我的代码中括号的数量、函数关键字等。
我的咖喱函数:
> 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"
这对于例如聚合特别好:
> 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
我发现它比以下更优雅和可编辑:
> aggregate(df$t, df["l"], function(x)paste(collapse="",toupper(x)))
l x
1 1 ADG
2 2 BCH
3 3 EFIJ
基本上我想知道 - 这已经为 R 完成了吗?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
roxygen 包中有一个名为 Curry 的函数。< br>
通过 R Mail Archive 上的此对话找到。
There is a function called Curry in the roxygen package.
Found via this conversation on the R Mail Archive.
如果您希望变量的“名称”准确传递,则需要更复杂的方法。
例如,如果您执行
plot(rnorm(1000),rnorm(1000))
那么您将在 x 轴和 y 轴上获得漂亮的标签。另一个例子是 data.frame并不是说 data.frame 已经为列分配了有用的名称。
Curry 的某些实现可能无法正确执行此操作,从而导致不可读的列名称和绘图标签。相反,我现在使用这样的东西:
这很复杂,但我认为它是正确的。
match.call
将捕获所有参数,完全记住定义参数的表达式(这对于漂亮的标签是必要的)。问题是它捕获了太多的参数——不仅是...
,还有FUN
。它还会记住正在调用的函数的名称 (Curry
)。因此,我们要删除
.orig
中的前两个条目,以便.orig
实际上只对应于...
参数。这就是为什么我们执行 .orig[[1]]<-NULL 两次 - 每次删除一个条目并将其他所有内容向左移动。这样就完成了定义,我们现在可以执行以下操作来获得与上面完全相同的结果关于
envir=parent.frame()
的最后说明。我用它来确保如果您有名为“.inner”或“.orig”的外部变量,不会出现问题。现在,所有变量都在调用 curry 的地方进行评估。A more complex approach is required if you want the 'names' of the variables to pass through accurately.
For example, if you do
plot(rnorm(1000),rnorm(1000))
then you will get nice labels on your x- and y- axes. Another example of this isdata.frame
Not that the data.frame has assigned useful names to the columns.
Some implementations of Curry may not do this properly, leading to unreadable column names and plot labels. Instead, I now use something like this:
This is quite complex, but I think it's correct.
match.call
will catch all args, fully remembering what expressions defined the args (this is necessary for nice labels). The problem is that it catches too many args -- not just the...
but also theFUN
. It also remembers the name of the function that's being called (Curry
).Therefore, we want to delete these first two entries in
.orig
so that.orig
really just corresponds to the...
arguments. That's why we do.orig[[1]]<-NULL
twice - each time deletes an entry and shifts everything else to the left.This completes the definition and we can now do the following to get exactly the same as above
A final note on
envir=parent.frame()
. I used this to ensure that there won't be a problem if you have external variables called '.inner' or '.orig'. Now, all variables are evaluated in the place where the curry is called.在 purrr 包中,现在有一个部分函数
in package purrr ,now there is a function partial
如果您已经在使用 tidyverse 的 purrr 软件包,则 purrr::partial 是柯里化函数的自然选择。从 purrr::partial 的描述来看:
If you are already using the purrr package from tidyverse, then purrr::partial is a natural choice to curry functions. From the description of purrr::partial:
这两个函数实际上都存在于
roxygen
包中 (在此处查看源代码”(最初基于 Byron Ellis 在 R-Help 上的解决方案):注意
Reduce
函数的用法,这在尝试进行函数式编程时非常有帮助有关更多详细信息,请参阅 ?Reduce(其中还涵盖其他函数,例如Map
和Filter
)。还有你的 Curry 示例(用法略有不同):
这是一个展示
Compose
实用程序的示例(对字母应用三个不同的函数):你的最终示例将像这样工作:
最后,这里是使用
plyr
执行相同操作的方法(也可以使用by
或aggregate
轻松完成,如已经所示):Both of these functions actually exist in the
roxygen
package (see the source code here) from Peter Danenberg (was originally based on Byron Ellis's solution on R-Help):Note the usage of the
Reduce
function, which can be very helpful when trying to do functional programming in R. See ?Reduce for more details (which also covers other functions such asMap
andFilter
).And your example of Curry (slightly different in this usage):
Here's an example to show the utility of
Compose
(applying three different functions to letters):And your final example would work like this:
Lastly, here's a way to do the same thing with
plyr
(could also easily be done withby
oraggregate
as already shown):R 中函数式编程的标准位置现在是函数库。
来自图书馆:
示例:
CRAN:
https://cran.r-project.org/web/packages/function /index.html
PS:该库替代了
ROxigen
库。The standard place for functional programming in R is now the
functional
library.From the library:
Example:
CRAN:
https://cran.r-project.org/web/packages/functional/index.html
PS: This library substitutes the
ROxigen
library.