R语言 编写自己的/自定义管道操作符

gzszwxb4  于 2023-05-04  发布在  其他
关注(0)|答案(1)|浏览(153)

我想写一个自定义管道操作符,其中使用的操作符名称是open。可能是E。例如%>%%|%:=、...可能需要根据所需的 * 运算符优先级 * 进行选择,如Same function but using for it the name %>% causes a different result compared when using the name :=中所解释的。
使用的占位符名称是open,但._是常见的,它需要显式放置(不自动放置为第一个参数)。

评测环境开放。但是在this answer中,似乎应该避免使用用户环境。

它应该能够在用户环境中保留值,以防它与占位符同名。
它应该能够更新用户环境中的值,包括占位符的名称。
它应该从左到右求值
目前我有:

`:=` <- function(lhs, rhs) {
  e <- exists(".", parent.frame(), inherits = FALSE)
  . <- get0(".", envir = parent.frame(), inherits = FALSE)
  assign(".", lhs, envir=parent.frame())
  on.exit(if(identical(lhs, get0(".", envir = parent.frame(), inherits = FALSE))) {
            if(e) {
              assign(".", ., envir=parent.frame())
            } else {
              if(exists(".", parent.frame())) rm(., envir = parent.frame())
            }
          })
  eval(substitute(rhs), parent.frame())
}

但尝试时失败:

. <- 0
1 := assign(".", .)
.
#[1] 0

下面给出了预期的结果,但我不确定它是否真的从左到右计算。

o3imoua4

o3imoua41#

这意味着你需要一个优先级在算术运算
这就排除了任何%>%操作,:=是一个不错的选择,我们也可以使用?,让我们使用:=
assign()<-默认情况下通常执行相同的操作。但你的例子暗示了另一种情况:
您希望assign(".", "foo")覆盖旧点,但names(.) <- "foo"(可能还有. <- "foo")覆盖新点,而不影响旧点。
我相信实现这一点的唯一方法是特殊情况assign(),我在下面这样做,你的测试是满意的。
有了这个解决方案,我们评估的表达式在一个子环境的调用者,继承了所有的值,除了点,这是在这个孩子的环境,并修改分配功能,分配在调用者时,环境参数不提供。

`:=` <- function(lhs, rhs) {
  pf <- parent.frame()
  rhs_call <- substitute(rhs)
  assign2 <- function (x, value, pos = -1, envir = as.environment(pos), inherits = FALSE, 
                       immediate = TRUE) {
    if (missing(pos) && missing(envir)) envir <- pf
    assign(x, value, envir = envir, inherits = inherits, immediate = immediate)
  }
  eval(rhs_call, envir = list(. = lhs, assign = assign2), enclos = pf)
}

1 := identity(.)
#> [1] 1
.
#> Error in eval(expr, envir, enclos): object '.' not found

. <- 2
1 := identity(.)
#> [1] 1
.
#> [1] 2

1 := assign("x", .)
x
#> [1] 1

"x" := assign(., 2)
x
#> [1] 2

1 := assign(".", .)
.
#> [1] 1

"." := assign(., 2)
.
#> [1] 2

x <- 1 := {names(.) <- "foo"; .}
x
#> foo 
#>   1

1 := . + 2 := . * 3
#> [1] 9

创建于2023-05-03带有reprex v2.0.2

相关问题