简体   繁体   English

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

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

With the magrittr pipe, one could use backticks ( ` ) to include special functions 1 in the pipe chain.使用magrittr管道,可以使用反引号 (`) 在管道链中包含特殊功能1 For example:例如:

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

# and

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

are the same as是一样的

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

# and

3 - 4 
#> [1] -1

However, the native R pipe |> does not (yet?) allow to do that.但是,原生 R 管道|>不允许(还?)这样做。 For example:例如:

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

Is there a reason why this has not been technically implemented (in case, what is the reason and are there plans to change this?) and are there any workarounds that are not too tortuous?有没有在技术上实现这一点的原因(以防万一,原因是什么,是否有计划改变它?)并且是否有任何不太曲折的解决方法?


1 I don't know how to correctly refer to those functions (behind operators such as + or [] ) that need backticks to be called in their standard function form. 1我不知道如何正确引用那些需要以标准函数形式调用反引号的函数(在+[]等运算符后面)。 Please edit where I say "special functions" if a more appropriate expression exists.如果存在更合适的表达式,请编辑我说“特殊功能”的地方。

The help file for the native pipe operator |> states:本机管道运算符的帮助文件|>指出:

To avoid ambiguities, functions in rhs calls may not be syntactically special, such as + or if.为避免歧义,rhs 调用中的函数在语法上可能不是特殊的,例如 + 或 if。

So it is not that the [ function is not implemented in the pipe, but rather that the [ symbol has been specifically prevented from being used in the pipe to prevent parsing ambiguities.所以不是[函数没有在管道中实现,而是[符号被明确禁止在管道中使用,以防止解析歧义。 There is certainly a case for arguing that the syntax '['(op1, op2) or '-'(op1, op2) could be confusing for new users, and results in code that is less clean and idiomatic.肯定有理由认为语法'['(op1, op2)'-'(op1, op2)可能会使新用户感到困惑,并导致代码不那么干净和惯用。 There may be more to it than that - perhaps some edge cases where there would be genuine parsing ambiguity, but I can't think of any, as long as backticks are used around special symbols.可能还不止这些——也许在某些极端情况下会出现真正的解析歧义,但我想不出任何情况,只要在特殊符号周围使用反引号即可。

Anyway, this means you can define a function as an alias for [ (a bit like magrittr's extract ), for example:无论如何,这意味着您可以将函数定义为[的别名(有点像 magrittr 的extract ),例如:

obtain <- `[`

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

takeaway <- `-`

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

You may use an anonymous function您可以使用匿名函数

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

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

Some workarounds are to surround [ with parentheses, use (\\(x) x[1])() notation, use do.call or find a function another function to perform the required operation.一些解决方法是将[括在括号中,使用(\\(x) x[1])()表示法,使用do.call或找到另一个函数来执行所需的操作。 The first 4 below are general workarounds.下面的前 4 个是一般的解决方法。 the next two use the Bizarro pipe and magrittr pipe whereas the remainder depend on the particular operation.接下来的两个使用Bizarro 管道magrittr 管道,而其余​​的则取决于特定的操作。

The last three examples below are less general than the others but show that sometimes using a different approach can work.下面的最后三个示例不如其他示例通用,但表明有时使用不同的方法可以奏效。

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

It appears to be a matter of taste, but since it has not been mentioned in the other answers, here is my preferred solution for using special functions in the native pipe.这似乎是一个品味问题,但由于其他答案中没有提到它,这是我在本机管道中使用特殊功能的首选解决方案。 Define the identity function and wrap the special functions in it.定义恒等函数并将特殊函数包装在其中。

id <- \(f) f

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

mtcars |> 
  id(`$`)("cyl")
#>  [1] 6 6 4 6 8 6 8 4 4 6 6 8 8 8 8 8 8 4 4 4 4 8 8 8 8 4 4 4 8 6 8 4

2 |> 
  id(`/`)(0)
#> [1] Inf

Created on 2022-01-18 by the reprex package (v2.0.1)reprex 包(v2.0.1)于 2022-01-18 创建

To add another possible workaround, you can use .Primitive like this:要添加另一种可能的解决方法,您可以像这样使用.Primitive

3 |> .Primitive("+")(4)
[1] 7

c("a","b") |> .Primitive("[")(1)
[1] "a"

The simplest solution is just add {} around the function on the RHS that generates the error "not supported in RHS call of a pipe":最简单的解决方案是在 RHS 上的函数周围添加{} ,它会生成错误“在 RHS 管道调用中不支持”:

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

and

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

Created on 2022-12-24 by the reprex package (v2.0.1)reprex 包(v2.0.1) 创建于 2022-12-24

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM