使用 Tidyverse 的简单管道中的 assign() 行为不一致

Inconsistent assign() behavior in simple piping with Tidyverse

通过简单地改变连接步骤中的参数顺序,我可以得到下面的代码 运行。我刚刚安装了截至 post (1.3.1) 的最新版本的 Tidyverse,我使用的是 R 版本 4.1.1 (2021-08-10),“Kick Things”。请结束我的疯狂:

更新:

library(dplyr)

#Doesn't run
if(exists("test")) rm("test")
iris%>%
  assign(x = "test",value = .,envir = .GlobalEnv)%>%
  left_join(x = test,y =. ,by="Species")

#Runs
if(exists("test")) rm("test")
iris%>%
  assign(x = "test",value = .,envir = .GlobalEnv)%>%
  left_join(x = .,y =test ,by="Species")

这里的管道让事情变得有点混乱,但如果我们编写与嵌套函数相同的代码,我们会得到相同的效果:

#Doesn't run
if(exists("test")) rm("test")
left_join(x = test, y = assign("test", iris, envir = .GlobalEnv), by = "Species")

#Runs
if(exists("test")) rm("test")
left_join(x = assign("test", iris, envir = .GlobalEnv), y = test, by = "Species")

当你看到它是这样写的时,第一个版本没有 运行 的原因现在就明白了:你在 non-existent 对象上调用 left_join;由于 left_join 是 S3 泛型,它仅评估 x 以确定方法分派,并将所有其他参数作为未评估的承诺传递给 left_join.data.frame。由于y没有被计算,test没有被写入,所以我们得到一个test not found错误。

在第二个版本中,y 参数直到在 left_join.data.frame 中被要求时才会被计算,而在它被计算时,test 已经被写入。

所以这种奇怪的行为是懒惰评估的结果。