53

假设我们有以下功能:

foo <- function(x)
{
    line1 <- x
    line2 <- 0
    line3 <- line1 + line2
    return(line3)
}

我们想将第二行更改为:

    line2 <- 2

你会怎么做?

一种方法是使用

fix(foo)

并改变功能。

另一种方法是再次编写函数。

还有其他方法吗?(记住,任务只是改变第二行)

我想要以某种方式将函数表示为字符串向量(嗯,字符),然后更改其中一个值,然后再次将其转换为函数。

4

5 回答 5

43

有一个body<-功能可以让您分配该功能的新内容。

body(foo)[[3]] <- substitute(line2 <- 2)
foo
#-----------    
function (x) 
{
    line1 <- x
    line2 <- 2
    line3 <- line1 + line2
    return(line3)
}

(“{”是 body(foo)[[1]] 并且每一行是列表的一个连续元素。因此第二行是表达式列表中的第三个元素。插入的元素需要是未计算的表达式而不是文本.)

还有一个相应的formals<-函数可以让人们在参数对列表上执行类似的手术。

注意:fixInNamespace可能比fix函数调用加载包中的附属函数资源更好。从控制台使用时,两者fix都会将结果分配给.GlobalEnv.

于 2010-03-21T02:00:30.083 回答
27

或者看看调试功能trace()。它可能不是您正在寻找的东西,但它可以让您尝试更改,并且它具有很好的功能,您可以随时使用untrace(). trace()base软件包的一部分,并带有一个漂亮而全面的帮助页面。

首先调用as.list (body(foo))以查看代码的所有行。

as.list(body(foo))
[[1]]
`{`

[[2]]
line1 <- x

[[3]]
line2 <- 0

[[4]]
line3 <- line1 + line2

[[5]]
return(line3)

然后,您只需定义要添加到函数中的内容以及通过在trace().

trace (foo, quote(line2 <- 2), at=4)
foo (2)
[1] 4

我在一开始就说过,这trace()可能不是您要查找的内容,因为您并没有真正更改第三行代码,而是简单地将值重新分配给line2以下插入的代码行中的对象。如果您打印出您现在跟踪的函数的代码,它会变得更清楚

body (foo)
{
    line1 <- x
    line2 <- 0
    {
        .doTrace(line2 <- 2, "step 4")
        line3 <- line1 + line2
    }
    return(line3)
}
于 2010-03-16T21:43:08.323 回答
23

fix是我知道的最好的方法,尽管您也可以使用edit和重新分配它:

foo <- edit(foo)

这就是fix内部所做的。如果您想将更改重新分配给不同的名称,您可能需要这样做。

于 2010-03-16T21:12:00.487 回答
17

fixInNamespace就像fix, 对于包中的函数(包括那些尚未导出的函数)。

于 2010-06-07T10:19:01.890 回答
9

您可以使用“ body ”功能。此函数将返回函数体:

fnx = function(a, b) { return(a^2 + 7*a + 9)}
body(fnx)
# returns the body of the function

所以“编辑”函数的一个好方法是在赋值语句的左侧使用“body”:

body(fnx) = expression({a^2 + 11*a + 4})
于 2010-03-16T21:40:09.647 回答