如何在R中实现F#的前向管道运算符?

19

如何在R中实现F#的前向管道运算符?该运算符使得轻松地链接一系列计算成为可能。例如,当你有一个输入data并想要按顺序调用函数foobar时,你可以这样写:

data |> foo |> bar

不要写成bar(foo(data))。好处是你可以避免一些括号,计算的顺序和执行的顺序(从左到右)保持一致。在F#中,该运算符定义如下:

let (|>) a f = f a

似乎可以使用 %...% 作为二进制运算符,但这将如何工作?


6
如果您能更清晰地说明这个运算符的实际作用,那将非常有帮助,这样我们就不必自己去查找信息了。也许您的问题已经说明了,但对我来说有点过于简略了。 - Ben Bolker
3个回答

27

我不知道它在实际使用中能否很好地保持,但这似乎(?)可以做到你想要的,至少对于单参数函数而言...

> "%>%" <- function(x,f) do.call(f,list(x))
> pi %>% sin
[1] 1.224606e-16
> pi %>% sin %>% cos
[1] 1
> cos(sin(pi))
[1] 1

顺带一提,截至目前(2021年12月3日),除了magrittr/tidyverse管道符(%>%)外,在R中还有一个本地管道符|>(以及一个在开发版中可以启用的试验性=>运算符):例如,请参见这里


PS do.call 可能是多余的 -- 函数体可能只需要是 f(x),但如果你想要允许多个参数类似于 list(1,5) %>% [back-quote]x[back-quote],那么你就需要使用 do.call... - Ben Bolker

10

编辑:包现在已经提交到CRAN。包含示例。

magrittr包专门为此而设计。

install.packages("magrittr")

示例:

iris %>%
  subset(Sepal.Length > 5) %>%
  aggregate(. ~ Species, ., mean)

还有,请参阅vignette:http://cran.r-project.org/web/packages/magrittr/vignettes/magrittr.html如果你喜欢F#管道,它具有很多有用的功能,而谁不喜欢呢?!


5
问题在于你谈论的是完全不同的函数调用范式,所以不太清楚你想要什么。R 只使用在 F# 中将是元组参数(在 R 中命名),因此可以这样想。
fp = function(x, f) f(x)

这将执行调用,例如:

> fp(4, print)
[1] 4

这个等价,但在非元组情况下不能像 4 |> f x y 这样使用,因为 R 中没有这种语法。你可以尝试模仿 F# 的函数式行为,但会很笨拙:

fp = function(x, f, ...) function(...) f(x, ...)

那将始终是功能性的,因此链接将起作用。例如:
> tri = function(x, y, z) paste(x,y,z)
> fp("foo", fp("mar", tri))("bar")
[1] "mar foo bar"

但是由于R不会将不完整的调用转换为函数,因此它并没有真正的用处。相反,R基于元组概念具有更加灵活的调用方式。请注意,R使用功能和命令式范例的混合,因此它不是纯函数性的,因此不执行参数值匹配等操作。
编辑:由于您在问题中进行了更改,因为您只对语法和特殊情况感兴趣,请将上面的fp替换为中缀符号:
`%>%` = function(x, f) f(x)
> 1:10 %>% range %>% mean
[1] 5.5

(使用Ben的操作符 ;))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接