我想写一个自定义管道操作符,其中使用的操作符名称是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
下面给出了预期的结果,但我不确定它是否真的从左到右计算。
1条答案
按热度按时间o3imoua41#
这意味着你需要一个优先级在算术运算
这就排除了任何
%>%
操作,:=
是一个不错的选择,我们也可以使用?
,让我们使用:=
。assign()
和<-
默认情况下通常执行相同的操作。但你的例子暗示了另一种情况:您希望
assign(".", "foo")
覆盖旧点,但names(.) <- "foo"
(可能还有. <- "foo"
)覆盖新点,而不影响旧点。我相信实现这一点的唯一方法是特殊情况
assign()
,我在下面这样做,你的测试是满意的。有了这个解决方案,我们评估的表达式在一个子环境的调用者,继承了所有的值,除了点,这是在这个孩子的环境,并修改分配功能,分配在调用者时,环境参数不提供。
创建于2023-05-03带有reprex v2.0.2