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

Gre*_*sio 3 r function magrittr tidyverse

由于 %>% 运算符的工作原理,这两个函数不会给出相同的输出,但我不明白为什么?

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"
Run Code Online (Sandbox Code Playgroud)

我真的不明白为什么这会有所不同。

MrF*_*ick 5

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

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

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

quote(x |> substitute() |> deparse())
deparse(substitute(x))
Run Code Online (Sandbox Code Playgroud)

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

可以看magrittr管道函数的源码

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

您可以看到它已经如何用于substitute获取其参数的未计算表达式。承诺无法在这种间接方式中继续存在。