如何在R中的函数体中插入表达式

时间:2016-08-03 00:48:19

标签: r

我有一个函数f <- function(x){x}。我想将行x <- 2*x插入f,以便最终为

function(x){
    x <- 2*x
    x
}

我知道我应该使用body(),但到目前为止我只是想出了如何替换整个主体,这对我的真实目的来说是不切实际的。

4 个答案:

答案 0 :(得分:4)

这是另一种方式(使用magrittr来简化事情)

f <- function(x){x}
f(2)
# [1] 2
# library(magrittr)
body(f) <- body(f) %>% as.list %>% append(quote(x<-2*x), 1) %>% as.call
f(2)
# [1] 4

甚至只是

body(f) %<>% as.list %>% append(quote(x<-2*x), 1) %>% as.call %>% as.expression

但我觉得我可能会错过更简单的方式

你可以在没有magrittr的情况下编写更传统的函数......

funins <- function(f, expr = expression(x<-2*x), after=1) {
    body(f)<-as.call(append(as.list(body(f)), expr, after=after))
    f
}

您可以使用它来插入任何表达式

f <- function(x){x}
g <- funins(f, expression(print("hi"), x<-3*x))
f(2)
# [1] 2
g(2)
# [1] "hi"
# [1] 6

答案 1 :(得分:3)

这是我的评论作为答案。如果它是单线功能的话,如果保护的话:

f <- function(x){x}


fun <- f

bod <- body(fun)
if (trimws(as.character(bod[[1]])) == "{"){
    body(fun)[[2]] <- quote(x <- 2*x)
    if (length(bod) > 1) body(fun)[3:(1+length(bod))] <- bod[-1]
} else {
    body(fun)[[1]] <- as.name('{')
    body(fun)[[2]] <- quote(x <- 2*x)
    body(fun)[[3]] <- bod
}
fun
fun(3)

答案 2 :(得分:1)

f <- function(x) { x }
bdy <- deparse(body(f))
body(f) <- as.expression(parse(text=paste0(c(bdy[1], "x <- 2*x", bdy[2:3]), collapse="\n")))

了解你真正想做的事情将是gd。像这样的猴子修补功能听起来像个坏主意。

答案 3 :(得分:0)

hrbrmstr的答案为基础,这是一个易于使用的包装器,无需使用外部软件包

用于修补其他功能的功能。

patch.function <- function(fun, patch, position = 1) {
    # Deparse the body.
    fun.body <- deparse(body(fun))

    # Append the patch to function body where intended.
    patched.fun.body <- paste0(
        c(fun.body[1:position], patch, fun.body[(position + 1):length(fun.body)]),
        collapse = "\n"
    )

    # Parse and treat as an expression.
    expr <- as.expression(parse(text = patched.fun.body))

    return(expr)
}

假设我们要修补以下虚拟函数。

dummy.fun <- function() {
    print("- a line A of the function body.")
    print("- a line B of the function body.")
    print("- a line C of the function body.")
    print("- a line D of the function body.")
    print("- a line E of the function body.")
    print("- a line F of the function body.")
    print("- a line G of the function body.")
    print("- a line H of the function body.")
}

我们可以将其用作:

body(dummy.fun) <- patch.function(dummy.fun, "print('Before the A line of the body.')")
dummy.fun()

# Output:
# [1] "Before the A line of the body."
# [1] "- a line A of the function body."
# [1] "- a line B of the function body."
# [1] "- a line C of the function body."
# [1] "- a line D of the function body."
# [1] "- a line E of the function body."
# [1] "- a line F of the function body."
# [1] "- a line G of the function body."
# [1] "- a line H of the function body."


body(dummy.fun) <- patch.function(dummy.fun, "print('Before the D line of the body.')", position = 5)
dummy.fun()

# Output:
# [1] "Before the A line of the body."
# [1] "- a line A of the function body."
# [1] "- a line B of the function body."
# [1] "- a line C of the function body."
# [1] "Before the D line of the body."
# [1] "- a line D of the function body."
# [1] "- a line E of the function body."
# [1] "- a line F of the function body."
# [1] "- a line G of the function body."
# [1] "- a line H of the function body."