无法在 R 中对基管使用特殊 (`) 函数

Not possible to use special ( ` ) functions with base pipe in R

对于 magrittr 管道,可以使用反引号 (`) 在管道链中包含特殊函数1。 例如:

library(magrittr)
c(7, 6, 5) %>% sort() %>% `[`(1)
#> [1] 5

# and

3 %>% `-`(4)
#> [1] -1

相同
v <- c(7, 6, 5)
v <- sort(v)
v[1]
#> [1] 5

# and

3 - 4 
#> [1] -1

然而,原生 R 管道 |> 不允许(还?)这样做。例如:

c(7, 6, 5) |> sort() |> `[`(1)
#> Error: function '[' not supported in RHS call of a pipe

# and

3 |> `-`(4)
#> Error: function '-' not supported in RHS call of a pipe

是否有技术上未实施的原因(万一,原因是什么,是否有计划改变它?),是否有任何不太曲折的解决方法?


1 我不知道如何正确引用那些需要反引号的函数(在 +[] 等运算符后面)以其标准函数形式调用。如果存在更合适的表达式,请编辑我说“特殊功能”的地方。

您可以使用匿名函数

c(7, 6, 5) |> sort() |> {function(x) x[1]}()
#[1] 5

3 |> {function(x) x - 4}()
#[1] -1

本机管道运算符的帮助文件 |> 指出:

To avoid ambiguities, functions in rhs calls may not be syntactically special, such as + or if.

所以不是[函数没有在管道中实现,而是[符号 已被特别禁止在管道中使用,以防止解析歧义。肯定有理由争论语法 '['(op1, op2)'-'(op1, op2) 可能会让新用户感到困惑,并导致代码不那么干净和惯用。可能不止于此 - 也许在某些边缘情况下会存在真正的解析歧义,但我想不出任何,只要在特殊符号周围使用反引号即可。

无论如何,这意味着你可以定义一个函数作为[的别名(有点像magrittr的extract),例如:

obtain <- `[`

c(7, 6, 5) |> sort() |> obtain(1)
#> [1] 5

takeaway <- `-`

c(7, 6, 5) |> sort() |> takeaway(1)
#> [1] 4 5 6

一些解决方法是用括号将 [ 括起来,使用 (\(x) x[1])() 符号,使用 do.call 或找到一个函数另一个函数来执行所需的操作。下面的前 4 个是一般解决方法。接下来的两个使用 Bizarro pipe and magrittr pipe 而其余部分取决于特定的操作。

下面的最后三个示例不如其他示例通用,但表明有时使用不同的方法是可行的。

c(7, 6, 5) |> sort() |> (`[`)(1)
## [1] 5

c(7, 6, 5) |> sort() |> (\(x) x[1])()
## [1] 5

c(7, 6, 5) |> sort() |> list(1) |> do.call(what = `[`)
## [1] 5

`%[%` <- `[`
c(7, 6, 5) |> sort() |> `%[%`(1)
## [1] 5

c(7, 6, 5) |> sort() ->.; .[1]  # Bizarro pipe
## [1] 5

library(magrittr)
c(7, 6, 5) %>% sort() %>% .[1]
## [1] 5

c(7, 6, 5) |> sort() |> head(1) 
## [1] 5

c(7, 6, 5) |> sort() |> .subset(1)
## [1] 5

3 |> c(-4) |> sum()
## [1] -1