Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 用多个值替换表达式中的一个符号_R_Metaprogramming_Static Code Analysis - Fatal编程技术网

R 用多个值替换表达式中的一个符号

R 用多个值替换表达式中的一个符号,r,metaprogramming,static-code-analysis,R,Metaprogramming,Static Code Analysis,给定任意固定表达式,我想用多个值的集合替换单个符号。示例: Expression | Symbol | Replace with | Desired Output ----------------------------------------------------------------------------------------- f(x, 5) | x | a = 1, b = sym, c = "char" | f

给定任意固定表达式,我想用多个值的集合替换单个符号。示例:

Expression       | Symbol | Replace with               | Desired Output
-----------------------------------------------------------------------------------------
f(x, 5)          | x      | a = 1, b = sym, c = "char" | f(a = 1, b = sym, c = "char", 5)
g(f(h(y)), z)    | y      | 1, 2, 3                    | g(f(h(1, 2, 3)), z)
g(f(h(y), z), z) | z      | 4, x                       | g(f(h(y), 4, x), 4, x)
substitute()
函数很接近,但它不是我想要的。在下面的示例中,我想将
f(x)
转换为
f(1,b=4,c=d)
,但我还没有找到正确的
env
参数

替换(
expr=f(x),
env=list(x=list(1,b=4,c=rlang::sym(“d”))
)
#>f(列表(1,b=4,c=d))
替代品(
expr=f(x),
env=list(x=as.call(c(quote(x),1,b=4,c=quote(d)))[-1])
)
#>f(1(b=4,c=d))
由(v0.2.1)于2019-02-09创建

是否有可能找到一个
env
,使得
替换(f(x),env)
等于
f(1,b=4,c=d)

备注:

  • 在上面,重要的是我们从
    f(x)
    开始。我们不能简单地将
    写成.call(c(quote(f),env))
  • 激励用例在和中进行了描述
  • 我们不能使用
    来自tidy evaluation,因为中的所有tidy evaluation都需要单独处理
  • 这篇文章取代了不太清楚的内容

    • 这个答案很笨拙,但(我认为)它能满足你的需要;这篇文章的灵感来源于一篇有点相关的文章:

      multi_substitute <- function(expr, key, ...) {
          expr <- deparse(substitute(expr))
          key <- deparse(substitute(key))
          # The following line is the bit I got from the mentioned SO answer
          l <- sapply( substitute(list(...)), deparse)[-1] 
          l <- paste(names(l), l, sep = " = ")
          l <- sub("^ = ", "", l)
          l <- paste(l, collapse = ",")
          vals <- deparse(substitute(...))
          result <- sub(key, l, expr)
          return(parse(text = result)[[1]])
      }
      multi_substitute(f(x), x, 1, b = 4, c = quote(d))
      # f(1, b = 4, c = quote(d))
      

      multi_-substitute这里是一个拼接函数

      splice <- function(x, replacements) {
        if (is(x, "call")) {
          as.call(do.call("c",lapply(as.list(x), splice, replacements), quote=T))
        } else if (is(x, "name")) {
          if (deparse(x) %in% names(replacements)) {
            return(replacements[[deparse(x)]])
          } else {
            list(x)
          }
        } else {
          list(x)
        }
      }
      
      基本上,您只需交换符号名称。它还可以处理列表中没有的单变量替换

      splice(quote(f(x,5)), list(x=7))
      # f(7, 5)
      

      您基本上需要通过将调用作为列表进行操作来重新编写调用。这就是tidyverse函数在幕后所做的。他们截取当前调用,重新编写它,然后评估新扩展的调用<代码>替换
      永远不会起作用,因为您不仅仅是用一个值替换一个符号。您需要更改传递给函数的参数数量。

      谢谢您的尝试,但我宁愿避免文本替换。去parsing和解析速度很慢,文本替换有边缘情况。例如,
      multi_-substitute(f(not_x,x),x,1,b=4,c=quote(d))
      等于
      f(not_1,b=4,c=quote(d),x)
      而不是所需的
      f(not_x,1,b=4,c=quote(d))
      。非常感谢,@MrFlick!很高兴我现在知道了do.call(quote=TRUE)
      splice(quote(f(x,5)), list(x=7))
      # f(7, 5)