是否存在客观原因,使得在编写R语言包时应避免使用来自R软件包magrittr
的管道运算符pipe operators,例如%>%
?
更具体地说,我想知道使用管道运算符是否可能导致编码冲突或对性能产生(正面或负面)影响。我正在寻找此类情况的具体、具体示例。
是否存在客观原因,使得在编写R语言包时应避免使用来自R软件包magrittr
的管道运算符pipe operators,例如%>%
?
更具体地说,我想知道使用管道运算符是否可能导致编码冲突或对性能产生(正面或负面)影响。我正在寻找此类情况的具体、具体示例。
像R语言中所有高级函数一样,%>%
需要较大的开销,因此不要在循环中使用它(包括隐式循环,例如*apply
系列或dplyr
和data.table
等软件包中的每个组的循环)。以下是一个例子:
library(magrittr)
x = 1:10
system.time({for(i in 1:1e5) identity(x)})
# user system elapsed
# 0.07 0.00 0.08
system.time({for(i in 1:1e5) x %>% identity})
# user system elapsed
# 15.39 0.00 16.68
|>
没有额外开销。 - Mikko Marttila往一个包中添加依赖项不应该轻率行事。一般来说,每个包所依赖的其他包都会增加未来维护风险,因为这些依赖项可能会更新,或者在依赖项停止维护的情况下。此外,这也会使得其他人在安装你的包时稍微麻烦一些——尤其是在网络连接不可靠的情况下,或者某些系统或硬件上安装某些包比较困难的情况下才会明显感觉到。但如果有人想将你的包放到一个闪存驱动器上以在其他地方安装,他们也需要确保拥有你的所有依赖项(及其依赖项...)。
Base R和默认包已经有很长的历史了,R-Core非常注重不引入会破坏下游依赖项的更改。 magrittr
则要新得多,看起来它首次出现在CRAN上是在2014年2月。
实际上,magrittr
已经稳定运行,并且看起来是一个低风险依赖项。特别是如果你只是导入%>%
并忽略它提供的更深奥的运算符(如dplyr
,tidyr
等),那么你可能是相当安全的。它的流行几乎可以保证,即使它的创建者放弃了维护,也会有其他人接手维护。
现在在2022年,我们已经有了几个R版本,其中包含基础管道|>
,因此只要你能运行R版本4.1.0或更高版本,就有了一个很好的没有依赖性的替代选择。
tidyverse
超级包发明之前的,可能是对为什么需要这个发明的一个相当简洁的解释。 - undefined管道范式与“标准函数式编程”相比颠倒了函数应用的表现顺序。这是否会产生不良后果取决于函数符号学(我的原始拼写错误是打算写成“语义”,但是拼写检查器认为我是指符号学
,这似乎也可以)。我认为管道创建的代码不太易读,但这是因为我已经训练自己从“内部到外部”来观察编码。比较一下:
y <- func3 ( func2( func1( x) ) )
y <- x %>% func1 %>% func2 %>% func3
依我的看法,第一个更易读,因为信息是向外(并且始终向左)“流动”的,并以最左侧位置的y
结束,而第二个中的信息则向右“流动”,然后“掉头”向左发送。管道范式还允许无参函数应用,我认为这增加了出错的可能性。仅使用位置参数匹配的R编程常常会产生完全不可理解的错误消息,而自律地始终(或几乎总是)使用参数名称具有更多信息的错误消息的好处。 y <- func3 %<% func2 %<% func1 %<% x
# Or
x %>% func1 %>% func2 %>% func3 -> y
我认为这实际上是 pkg-magrittr 的原始设计的一部分,其中我认为包括“左通道”和“右通道”。所以这可能是一个人因素设计问题。R具有从左到右的结合性,dplyr/magrittr 管道范例的典型用户通常遵循这个规则。我可能有僵硬的脑症候群,而你们所有年轻人可能都是未来,所以你们要做出选择。我真的很欣赏 Hadley 的目标,即使文件和 SQL 服务器被视为广义串行设备。
David Robinson 提供的示例表明跟踪参数是一个大问题,我完全同意。我的常规方法是使用制表符和空格来突出显示层次结构:
func3 ( func2(
func1(x, a), # think we need an extra comma here
b, c), # and here
d, e, f)
x %>% func1(a) %>% func2(b, c) %>% func3(d, e, f)
毋庸置疑,使用语法感知的编辑器检查缺少逗号或括号会更容易,但在上述例子中未使用此类工具时,堆叠/间距方法确实突出了我认为存在的语法错误。(当我遇到困难时,我也会快速添加参数名称,但我认为这对于管道代码策略同样适用。)
->
,这让我很疯狂!不过,我想每个人都有自己的喜好。 - Gregor Thomas->
在 R 中是可解析的。我只是想说,如果你使用右向数据流,那么右赋值似乎更加一致。 - IRTFMfunc3 ( func2( func1(x, a) b, c) d, e, f)
或者 x %>% func1(a) %>% func2(b, c) %>% func3(d, e, f)
?就哪个参数与哪个函数相对应而言,哪个更清晰? - David Robinson
magrittr
进行基于管道的编程时,是否存在潜在的错误或冲突,类似于使用NSE时可能出现的情况?我正在寻找具体的、具体的例子,而不是关于使用管道的有用性或智慧的一般意见。” - Ben Bolker