在函数 r 中更改参数名称

change argument names inside a function r

我正在尝试调整函数内参数的名称。我想创建一个获取函数主体的过程,查找 x,将每个 x 更改为 x0,然后将函数恢复到原来的样子。举个例子:

f = function(x, y) -x^2 + x + -y^2 + y
# Take old names
form_old = names(formals(f))
# Make new names
form_new = paste0(form_old, 0)
# Give f new formals
formals(f) = setNames(vector("list", length(form_new)), form_new)
# Copy function body
bod = as.list(body(f))
for (i in 1:length(form_new)) {
  bod = gsub(form_old[i], form_new[i], bod)
}
# return from list to call ?
body(f) = as.call(list(bod))
f(1, 1) # produces an error

到目前为止,此代码会将所有变量名称从 x 更改为 x0 并从 yy0。但是,bod 的最终输出是字符向量而不是调用。我现在如何将其改回电话?

提前致谢!

有几种方法可以到达这里。按照你的代码,我会用这样的东西:

f = function(x, y) -x^2 + x + -y^2 + y
# Take old names
form_old = names(formals(f))
# Make new names
form_new = paste0(form_old, 0)
deparse(body(f)) -> bod
for (i in 1:length(form_new)) {
  bod = gsub(form_old[i], form_new[i], bod, fixed = TRUE)
}
formals(f) = setNames(vector("list", length(form_new)), form_new)
body(f) <- parse(text = bod)
f(1, 1) 

当然有更好的方法来做你想做的事情,不需要修改函数。话虽如此,您绝对不想用正则表达式替换变量,这可能会带来各种各样的问题。通常,尝试将代码作为字符串来操作会导致问题,例如,像 tricky <- function(x, y) { tst <- "x + y"; -xx*x + yy*y } 这样的函数,其中字符串和变量名重叠,将导致错误的结果。

这是一个采用递归方法(Recall)遍历表达式树的函数(使用'stack'类型结构可以避免递归,但对我来说似乎更难)。

## Function to replace variables in function body
## expr is `body(f)`, keyvals is a lookup table for replacements
rep_vars <- function(expr, keyvals) {
    if (!length(expr)) return()
    for (i in seq_along(expr)) {
        if (is.call(expr[[i]])) expr[[i]][-1L] <- Recall(expr[[i]][-1L], keyvals)
        if (is.name(expr[[i]]) && deparse(expr[[i]]) %in% names(keyvals))
            expr[[i]] <- as.name(keyvals[[deparse(expr[[i]])]])
    }
    return( expr )
}

## Test it
f <- function(x, y) -x^2 + x + -y^2 + y
newvals <- c('x'='x0', 'y'='y0')  # named lookup vector

newbod <- rep_vars(body(f), newvals)
newbod
# -x0^2 + x0 + -y0^2 + y0

## Rename the formals, and update the body
formals(f) <- pairlist(x0=bquote(), y0=bquote())
body(f) <- newbod

## The new 'f'
f
# function (x0, y0) 
# -x0^2 + x0 + -y0^2 + y0

f(2, 2)
# [1] -4

使用更难的函数,您希望避免修改字符串或其他名为 yyxx 的变量,例如,

tricky <- function(x, y) { tst <- "x + y"; -xx*x + yy*y }
formals(tricky) <- pairlist(x0=bquote(), y0=bquote())
body(tricky) <- rep_vars(body(tricky), newvals)
tricky
# function (x0, y0) 
# {
#     tst <- "x + y"
#     -xx * x0 + yy * y0
# }
#