基R替换函数调用的参数名称



问题的最终目标是使用该语言上的r计算构建以下未赋值调用,其中lista_name50L由参数提供。

list(a_name = 50L)

内部看起来像

str(quote(list(a_name = 50L)))
# language list(a_name = 50L)
str(as.list(quote(list(a_name = 50L))))
#List of 2
# $       : symbol list
# $ a_name: int 50

我将把我的变量放在一个列表中,这样进一步的代码会更干净。

params = list(my_fun = as.name("list"), my_name = "a_name", my_value = 50L)
# What I tried so far?
# 1. The first thing that one would try
substitute(my_fun(my_name = my_value),
params)
#list(my_name = 50L) ## `my_name` was not substituted!
# 2. Workaround get the same output, but only after `setNames` call evaluation, so doesn't really answer the question about constructing specific call
substitute(setNames(my_fun(my_value), my_name), ## alternatively could be `structure(..., names=my_name)`
params)
#setNames(list(50L), "a_name")
# 3. Another workaround, not really computing on the language but parsing, and integer L suffix is gone!
with(expr = parse(text=paste0(my_fun, "(", my_name, " = ", my_value, ")"))[[1L]],
data = params)
#list(a_name = 50)
# 4. Working example using rlang
with(expr = rlang::call2(my_fun, !!my_name := my_value),
data = params)
#list(a_name = 50L)

在基r中有任何方法可以构造所需的调用吗基本上获得与rlang方式完全相同的输出,但使用基本r。

请注意,这个问题并不是严格要求rlang解决方案的问题的重复。这个问题询问了一种使用碱基r实现它的方法。如果没有方法实现它,我也想知道。非常感谢。

假设问题是如何生成一个call对象,该对象的函数是params的第一个参数,其单个参数名称是params的第二个分量的值,其参数值是params的第三个分量,那么c2就是调用对象。我们验证生成的cakl对象与问题中显示的rlang调用对象相同。

c2 <- as.call(setNames(params, c("", "", params2$my_name))[-2])
# verify that c2 equals the output of the rlang example in question
c1 <- with(expr = rlang::call2(my_fun, !!my_name := my_value), data = params)
identical(c1, c2)
## [1] TRUE

这是一般化的,因此如果调用有更多的参数,使得params的长度为n+2,并且params的第二个分量是长度为n的名称向量,那么它仍然有效。

如果你可以控制输入,我认为将输入列表定义为函数名有一个组件,每个参数有一个分量,其中组件的名称就是参数名称(而不是单独的参数来保存名称(会更有意义。在这种情况下,我们可以简单地写以下内容。实际上,上面所做的是将params转换为该形式,然后使用as.call,所以如果可能的话,我们还可以从一开始就提供该形式。

as.call(params2)  # params2[[1]] is func name, params2[-1] is named args

备注

要执行调用,只需使用:

eval(c2)

或者我们可以使用do.call:

do.call(as.character(params[[1]]), setNames(tail(params, -2), params[[2]]))

最新更新