magrittr 管道 %>% 在阴影中的作用

What the magrittr pipe %>% does in the shadows

提问人:Greg Mansio 提问时间:4/22/2023 最后编辑:MrFlickGreg Mansio 更新时间:4/22/2023 访问量:47

问:

这两个函数没有给出相同的输出,因为 %>% 运算符的工作方式,但我不明白为什么?

my_function <- function(x) {
 # Extract the name of x
 the_name_of_x <- deparse(substitute(x))
 print(the_name_of_x)
}

my_other_function <- function(x) {
 # Extract the name of x
 the_name_of_x <- x %>% substitute() %>% deparse()
 print(the_name_of_x)
}

# Example
my_function("zaza")
# [1] "\"zaza\""
my_other_function("zaza")
# [1] "x"

我真的想不通为什么这会有所作为。

R 函数 tidyverse magrittr

评论


答:

5赞 MrFlick 4/22/2023 #1

如果使用本机管道,则将获得与第一个管道相同的值

yet_another_function <- function(x) {
  # Extract the name of x
  the_name_of_x <- x |> substitute() |> deparse()
  print(the_name_of_x)
}

原因是管道实际上重写了语法树,因此它实际上不是一个函数。观察|>

quote(x |> substitute() |> deparse())
deparse(substitute(x))

但是是一个函数。它将出现在调用堆栈上。该函数使用非标准计算,这意味着它查看传递给函数的表达式。该函数无法完全重写调用。它将函数参数的 promise 计算到表达式中。 是一个特殊函数,因为如果要捕获 promise 指向的值,则需要在评估 promise 之前执行此操作。%>%substitute%>%substitute

您可以看到 magrittr 管道函数的来源

`%>%`
function (lhs, rhs) 
{
    lhs <- substitute(lhs)
    rhs <- substitute(rhs)
    kind <- 1L
    env <- parent.frame()
    lazy <- TRUE
    .External2(magrittr_pipe)
}

你可以看到它是如何用来获取其参数的未计算表达式的。承诺无法在这种间接性中幸存下来。substitute