R管道操作中函数message输出顺序反转原因及保留管道的解决方法
R原生管道符消息输出顺序反转问题原因及解决方案
原因说明
R原生管道|>本质是语法糖,x |> f1() |> f2()会被直接转换为嵌套调用f2(f1(x))。
R函数参数默认采用惰性求值机制:执行外层函数f2时,不会立刻计算传入的参数f1(x)的值,而是先执行f2体内不依赖参数的代码,也就是先输出message 2,直到f2需要使用参数x的值(即返回x的步骤)时,才会触发对f1(x)的求值,此时才会执行f1中的代码输出message 1,最终就出现了消息顺序反转的现象。
保留管道写法的规避方案
- 方案1:自定义函数开头添加
force()强制参数求值
在每个参与管道的函数第一行调用force(x),强制对传入的参数提前求值,触发上游管道步骤执行,修改后的代码示例:
f1 <- function(x){ force(x) message("message 1") x } f2 <- function(x){ force(x) message("message 2") x } x = 1 x |> f1() |> f2()
此时输出顺序会符合预期:先输出message 1,再输出message 2,最后返回结果。
- 方案2:替换为magrittr包的
%>%管道
magrittr管道%>%的求值逻辑为从左到右依次执行每一步,不会转换为嵌套调用,天然不存在顺序反转问题,使用示例:
library(magrittr) f1 <- function(x){ message("message 1") x } f2 <- function(x){ message("message 2") x } x = 1 x %>% f1() %>% f2()
- 方案3:无需修改原函数的临时处理
如果无法修改已有的自定义函数,可以在管道每一步外层添加force()调用,强制每一步执行完成后再进入下一个管道步骤:
x |> force(f1()) |> force(f2())
内容的提问来源于stack exchange,提问作者Phil
相关产品推荐
相关产品推荐

