暂时覆盖功能

时间:2014-07-11 12:51:09

标签: r methods

我想在我的包中提供一个名为“Sdt”的函数。它有多种方法,但它们都会导致Sdt.default(a,b,c,d),它会返回一个带有a,b,c和d的计算内容的命名向量。

但在某些情况下,我的软件包的用户需要扩展Sdt.default,例如,如果他/她想要尝试使用这四个变量进行其他一些计算。

所以我想:为什么不暂时覆盖这个功能?所以我尝试了类似的东西(当然是Sdt,但这是一个更好的玩具示例):

a <- function() print("FUNCTION A CALLED")
b <- function() print("FUNCTION B CALLED")
c <- function() a()
d <- function(){

  a()
  a <- b
  a()

  c()
}
d()

结果如下

[1] "FUNCTION A CALLED"
[1] "FUNCTION B CALLED"
[1] "FUNCTION A CALLED"

但我想要

[1] "FUNCTION A CALLED"
[1] "FUNCTION B CALLED"
[1] "FUNCTION B CALLED"

“&lt;&lt; - ”运算符可以在这个例子中工作,但是如果在包中定义了一个(),它会抛出错误消息,(“包中确定的函数不能被改变”或类似的东西)那)

TL; DR 如何暂时但完整地从包中的函数覆盖全局环境中的函数,以便所有后续和嵌套调用都使用更改的函数?

3 个答案:

答案 0 :(得分:3)

我不会同时使用assign<<-。我只想修改c()函数

a <- function() print("FUNCTION A CALLED")
b <- function() print("FUNCTION B CALLED")
c <- function(x = a) x() 
d <- function(){

  a()
  a <- b
  a()

  c(a)
}
d()

## [1] "FUNCTION A CALLED"
## [1] "FUNCTION B CALLED"
## [1] "FUNCTION B CALLED"

虽然没有参数的c()可以使用相同的

c()
## [1] "FUNCTION A CALLED"

答案 1 :(得分:3)

我是@ DavidArenburg解决方案的粉丝,但是如果要为所有要暂时覆盖的变量定义默认参数不是一个选项,这是另一种方式:

d <- function(){
  a()
  a <- b
  a()
  environment(c) <- environment()
  c()
}
d()
# [1] "FUNCTION A CALLED"
# [1] "FUNCTION B CALLED"
# [1] "FUNCTION B CALLED"
c()
# [1] "FUNCTION A CALLED"

答案 2 :(得分:1)

您可以使用assign功能将新创建的功能放入全局环境中 看看这个示例替换基本sum函数:

callSum <- function() sum(1)

main <- function(){

  # here we use the original sum function -> we expect 1
  print(sum(1))

  # let's create a new sum function returning always 100
  # and assign it to the global env. with name "sum"
  # (note that the name of this function object is not important, 
  # but the name used in assign is crucial)
  newSum <- function(v) {return(100)}
  assign("sum", newSum, envir=globalenv())

  # let's call sum(1) -> we expect 100
  print(sum(1))

  # let's call a function that calls sum(1) -> we expect 100
  print(callSum())

  # we don't want to return anything...
  invisible()
}

main()

打印:

[1] 1
[1] 100
[1] 100

但是,这不是一个干净的解决方案。

如果您认为需要经常在软件包实现和自定义实现之间切换,我建议创建一个Std的包装器,并在需要使用Std函数的任何地方使用它。这样,当您想要停止使用包版本时,您只需更改包装器实现,例如:

StdWrapper <- function(a,b,c,d){
   return(Std(a,b,c,d))
   # return(YourCustomStd(a,b,c,d))

   # as soon as you need to switch to a custom implementation,
   # just comment the first line and uncomment the second and vice-versa 
}