自 R 版本 4.1.0 起,管道符 |>
已经成为稳定版本的一部分。当将 lhs 传递到除第一个参数外的其他参数时,手册中的示例如下:
mtcars |> subset(cyl == 4) |> (function(d) lm(mpg ~ disp, data = d))()
或者在使用\(x)
时
mtcars |> subset(cyl == 4) |> (\(d) lm(mpg ~ disp, data = d))()
或者使用PIPEBIND,目前需要激活:
Sys.setenv(`_R_USE_PIPEBIND_` = TRUE)
mtcars |> subset(cyl == 4) |> . => lm(mpg ~ disp, data = .)
可以使用Bizarro pipe ->.;
替换 |>
如下:
mtcars |> subset(cyl == 4) ->.; lm(mpg ~ disp, data = .)
在R中,管道符号的一个目的是允许以一种可能使处理步骤顺序更易于理解的方式编写嵌套的调用序列,至少对我来说,->.;
也满足了这个要求。Bizarro管道不是一个真正的管道,但对我来说,它目前是一个受欢迎的替代品,尤其是在将lhs传递到除第一个参数以外的参数时。但当我使用它时,我得到评论不要使用它。
因此,我想知道Bizarro管道是否有缺点,推荐不要使用它?
到目前为止,我看到它在环境中创建或覆盖.
并保留此引用,这将在修改时强制进行复制。但是,当调用带有数据参数的函数时,还会创建对此数据的引用。而且当使用for
循环后,var
会留下。
for(i in iris) {}
tracemem(i) == tracemem(iris[[ncol(iris)]])
#[1] TRUE
此外,就性能而言,它并没有显示出太多的不利影响:
x <- 42
library(magrittr)
Sys.setenv(`_R_USE_PIPEBIND_` = TRUE)
#Nonsense operation to test Performance
bench::mark(x
, identity(x)
, "x |> identity()" = x |> identity()
, "x |> (\\(y) identity(y))()" = x |> (\(y) identity(y))()
, "x |> . => identity(.)" = x |> . => identity(.)
, "x ->.; identity(.)" = {x ->.; identity(.)}
, x %>% identity
)
# expression min median `itr/sec` mem_alloc `gc/sec` n_itr
# <bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl> <int>
#1 x 60.07ns 69.03ns 13997474. 0B 0 10000
#2 identity(x) 486.96ns 541.91ns 1751206. 0B 175. 9999
#3 x |> identity() 481.03ns 528.06ns 1812935. 0B 0 10000
#4 x |> (\(y) identity(y))() 982.08ns 1.08µs 854349. 0B 85.4 9999
#5 x |> . => identity(.) 484.06ns 528.06ns 1815336. 0B 0 10000
#6 x ->.; identity(.) 711.07ns 767.99ns 1238658. 0B 124. 9999
#7 x %>% identity 2.86µs 3.23µs 294945. 0B 59.0 9998
mtcars |> subset(cyl == 4) |> lm(formula = mpg ~ disp)
。我认为性能是重点的原因是它似乎是 |> 的主要动机因素,并且它放弃了大部分 %>% 和 bizarro pipe 的特性,以通过语法转换来实现它。我怀疑关于 bizarro pipe 的副作用参数是否真的具有实际重要性。 - G. Grothendieck