Rqu的反向行为

Ser*_*gey 2 r metaprogramming

bquote函数允许评估包含在.()调用中的表达式的部分.例如,

a <- 2
b <- 100
bquote(.(2 * a) * x + .(log10(b)))
Run Code Online (Sandbox Code Playgroud)

会回来的

4 * x + 2
Run Code Online (Sandbox Code Playgroud)

我想重写这个函数来评估除了.()调用内部的东西之外的所有东西.这是所需的行为:

a <- 2
b <- 100
bquote(2 * a * .(x) + log10(b))

> 4 * x + 2
Run Code Online (Sandbox Code Playgroud)

我知道要这样做,我必须检查抽象语法树并评估没有.()调用的早午餐,但我无法处理所有这些递归.

你能帮我写一下这样的功能吗?

G. *_*eck 5

subst将替换除.(...)中的变量之外的所有变量,该simplify函数将简化没有变量的子树 - 如果不需要简化,则省略简化部分.没有使用包裹.

subst <- function(e) {
   if (typeof(e) == "language") {
      if (identical(e[[1]], as.name("."))) e[[2]]
      else {
        if (length(e) > 1) e[-1] <- lapply(as.list(e[-1]), subst)
        e
      }
   } else {
      eval(e)
   }
}

simplify <- function(e) {
  if (typeof(e) == "language") {
     if (length(all.vars(e))) {
         if (length(e) > 1) {
           e[-1] <- lapply(as.list(e[-1]), simplify)
           e
         } else e
     } else eval(e)
  } else e
}

inverse_bquote <- function(x, SIMPLIFY = TRUE) {
   result <- subst(substitute(x))
   if (SIMPLIFY) simplify(result) else result
}
Run Code Online (Sandbox Code Playgroud)

现在测试一下.

a <- 2
b <- 100

inverse_bquote(2 * a * .(x) + log10(b))
## 4 * x + 2

# without simplification

inverse_bquote(2 * a * .(x) + log10(b), SIMPLIFY = FALSE)
## 2 * 2 * x + log10(100)
Run Code Online (Sandbox Code Playgroud)

更新:添加简化.做它是可选的.