【发布时间】:2012-11-15 17:14:07
【问题描述】:
我正在尝试覆盖 knitr 包的 tidy.source 函数。问题是tidy.source 是在formatR 包中定义的,它是由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" 都会显示在加载的命名空间的名称中。
假设main导入导出的sub函数exp.sub.func,该函数依次调用未导出的sub 函数 prv.sub.func。如果你想用你的 exp.sub.func.mod 改变/自定义 exp.sub.func,你可以考虑使用:
assign("exp.sub.func", exp.sub.func.mod, asNamespace ("sub"))
因此,通过运行sub::exp.sub.func,您将获得您的补丁版本(即exp.sub.func.mod)。
不幸的是,只要你的 exp.sub.func.mod 继续依赖 prv.sub.func,你就会得到错误:
Error in [...] : object 'prv.sub.func' not found
事实上:
environment(sub::exp.sub.func)
现在返回:<environment: R_GlobalEnv>,而在修补之前它是<environment: namespace:sub>。
问题是:如何将修补后的函数移动到正确的命名空间?
要解决上述问题,当然可以使用任何软件包;在我的例子中,我使用 knitr 和 formatR 作为主要和导入的命名空间,并使用 tidy.source() 作为修补函数。
【问题讨论】:
-
你为什么要覆盖
tidy.source? -
我最近需要做一些类似的事情,并将其格式化如下:
assignInNamespace("grid.curve", grid.curve, ns = "grid")。当我运行这个命令时,我修改后的grid.curve已经被引入工作区。这与您使用的规范略有不同,但在我看来,您的规范也应该可以工作。但是,我不是在继承的环境中工作。 -
@mnel 这是来自 Google 的 cmets 指南: > 短 cmets 可以放在代码之后,前面有两个空格,#,然后是一个空格。 google-styleguide.googlecode.com/svn/trunk/… 这也是很常见的注释做法,但是参数后的内联 cmets 不适用于“formatR”。
-
@BryanHanson 我确实喜欢你。 `function()print("My tidy.source"),' 仅用于使代码自包含。
-
可能值得在
formatR或knitr页面上提出有关更改tidying函数或格式样式的问题。
标签: r namespaces packages knitr