覆盖另一个包继承的包函数

ant*_*nio 5 namespaces packages r knitr

我试图覆盖包的tidy.source功能knitr.问题是tidy.sourceformatR包中定义,包由knitr包导入.如果我跑:

get("tidy.source", envir=asNamespace("knitr"))

我得到了原始代码.所以我很想覆盖tidy.source:

assignInNamespace ("tidy.source", function()print("My tidy.source"), "knitr"),

但我得到:

Error in bindingIsLocked(x, ns) : no binding for "tidy.source".

实际上tidy.source是定义formatR并继承的knitr.附:

assignInNamespace ("tidy.source", function()print("My tidy.source"), "formatR")

一切都显得顺利,但再次检查get("tidy.source", envir=asNamespace("knitr"))表明内部knitr没有任何变化.

有帮助吗?

编辑:

由于knitr/formatR的新开发版本,这个问题已经过时了.非常感谢Yihui注意到这个讨论,并决定更新他的包.看到:

https://github.com/yihui/formatR/commit/6f70360f359caa8d2bb33190a1c89530defb0e98

我绝对可以从Sweave切换到knitr.

关于覆盖进口包裹功能的一般性问题仍未解决.由于它与knitr/formatR无关,所以我用更一般的术语重述它.

假设您有一个包main导入包imp.如果加载前者,则"package:main"显示在附加的包列表中,"main""sub"显示两者,并显示加载的命名空间的名称.

假设主要进口导出的功能exp.sub.func,这就要求在原来的非出口功能prv.sub.func.如果你想改变/自定义exp.sub.funcexp.sub.func.mod,你可能会想到使用:

assign("exp.sub.func", exp.sub.func.mod, asNamespace ("sub"))
Run Code Online (Sandbox Code Playgroud)

因此,通过运行,sub::exp.sub.func您将获得修补版本(即exp.sub.func.mod).
不幸的是,只要您的exp.sub.func.mod继续依赖prv.sub.func,您就会收到错误:

Error in [...] : object 'prv.sub.func' not found
Run Code Online (Sandbox Code Playgroud)

事实上:

environment(sub::exp.sub.func) 
Run Code Online (Sandbox Code Playgroud)

现在返回:<environment: R_GlobalEnv>当它是<environment: namespace:sub>打补丁之前.

问题是:如何将修补的函数移动到正确的命名空间

要实现上述问题,您当然可以使用任何包; 在我的例子中,我使用knitrformatR作为主要和导入的命名空间,并使用tidy.source()作为修补函数.

GSe*_*See 3

更改formatR命名空间中的函数不会更改knit使用的内容,因为knit已经加载。因此,您可以卸载并重新加载它。

assignInNamespace("tidy.source", function()print("My tidy.source"), "formatR")
detach('package:knitr', unload=TRUE)
library(knitr)
get("tidy.source", envir=asNamespace("knitr"))
#function()print("My tidy.source")
Run Code Online (Sandbox Code Playgroud)