我正在尝试使用 rlang 包来构造一个执行赋值的表达式,给定一个右侧表达式(要分配的值)和一个左侧表达式(分配它的位置)。例如,假设我要构造和评估表达式a <- 5
:
> library(rlang)
> a <- "Not 5"
> lhs <- quo(a)
> rhs <- quo(5)
> eval_tidy(quo( (!!lhs) <- (!!rhs)) ) # Error
Error in (~a) <- (~5) : could not find function "(<-"
> eval_tidy(quo(`<-`(!!lhs, !!rhs))) # Error
Error in ~a <- ~5 : could not find function "~<-"
> eval_tidy(quo(`<-`(!!f_rhs(lhs), !!rhs))) # No error, but no effect
[1] 5
> stopifnot(a == 5)
Error: a == 5 is not TRUE
> print(a)
[1] "Not 5"
如您所见,上述构造和评估此分配的方法都没有达到预期的效果。有没有办法正确地做到这一点?
编辑:使用assign
而不是<-
不是一个好的解决方案,因为它只适用于变量,而不是对象的元素。例如,它不适用于:
> a <- list(ShouldBeFive="Not 5")
> lhs <- quo(a$ShouldBeFive)
编辑 2:我写了一个概念证明来展示我想要完成的事情。它定义了一个assign_general
允许任意左侧的函数,例如assign_general(a[[1]], 5)
等效于a[[1]] <- 5
. 但是,我的实现似乎有点骇人听闻,我不知道我可能错过了哪些极端情况,而且我仍然不确定是否有更直接的方法来做到这一点,所以我仍然有兴趣看看是否有人有一个更好的解决方案。