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)