首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >重写由另一个包继承的包函数

重写由另一个包继承的包函数
EN

Stack Overflow用户
提问于 2012-11-27 23:32:19
回答 3查看 1.9K关注 0票数 5

我试图重写tidy.source包的knitr函数。问题是tidy.source是在由knitr包导入的formatR包中定义的。如果我跑:

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内部什么都没有改变。

有什么帮助吗?

编辑:

这一问题部分是过时的,因为新的开发版本的针织/成型R。非常感谢一辉注意到这一讨论,并决定更新他的包裹。请参见:

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

我绝对可以从瑞典人转到针织者。

无论如何,有关导入包函数的覆盖的一般问题仍然没有解决。由于它不再与编织品/格式R包有关,所以我用更一般的术语重申它。

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

假设main导入导出的子函数exp.sub.func,后者依次调用非导出的子函数prv.sub.func。如果您想用您的exp.sub.func更改/自定义exp.sub.func.mod,您可以考虑使用:

代码语言:javascript
复制
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,您就会得到错误:

代码语言:javascript
复制
Error in [...] : object 'prv.sub.func' not found

事实上:

代码语言:javascript
复制
environment(sub::exp.sub.func) 

现在返回:<environment: R_GlobalEnv>,而它在修补之前是<environment: namespace:sub>

问题是:如何将修补好的函数移动到适当的命名空间?

为了实现上面的问题,您当然可以使用任何包;在我的示例中,我使用formatR和tidy.source作为main和导入的命名空间,使用tidy.source()作为修补函数。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-11-28 02:01:07

更改formatR命名空间中的函数不会更改针织r使用的内容,因为已经加载。所以,你可以卸载和重新装载它。

代码语言:javascript
复制
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")
票数 3
EN

Stack Overflow用户

发布于 2012-11-30 21:47:37

如果您想要的只是函数参数之后的注释,我在开发版中提供了对开发版的支持,您可以使用从吉突布安装它

通常,使用assignInNamespace()修改包是个坏主意,正如它的文档所示。

票数 2
EN

Stack Overflow用户

发布于 2012-11-30 13:53:37

这是一个可能的错误尝试,它允许tidy.source包中包含的函数参数之后的内联注释。

代码语言:javascript
复制
## ============ Possible (wrong?) ideas on inline comments ============

  tidy.source.mod=  function (source = "clipboard", keep.comment = getOption("keep.comment",
    TRUE), keep.blank.line = getOption("keep.blank.line", TRUE),
    keep.space = getOption("keep.space", FALSE), replace.assign = getOption("replace.assign",
        FALSE), left.brace.newline = getOption("left.brace.newline",
        FALSE), reindent.spaces = getOption("reindent.spaces",
        4), output = TRUE, text = NULL, width.cutoff = getOption("width"),
    ...)
{     
    if (is.null(text)) {
        if (source == "clipboard" && Sys.info()["sysname"] ==
            "Darwin") {
            source = pipe("pbpaste")
        }
        text = readLines(source, warn = FALSE)
    } 
    if (length(text) == 0L || all(grepl("^\\s*$", text))) {
        if (output)
            cat("\n", ...)
        return(list(text.tidy = "", text.mask = ""))
    } 
    text.lines = text
    if (keep.comment) {
        if (!keep.space)
            text.lines = gsub("^[[:space:]]+|[[:space:]]+$",
                "", text.lines)
        head.comment = grepl("^[[:space:]]*#", text.lines)
        if (any(head.comment)) {
            text.lines[head.comment] = gsub("\"", "'", text.lines[head.comment])
        }
        if (!keep.space) {
            head.comment = head.comment & !grepl("^\\s*#+'",
                text.lines)
            text.lines = reflow_comments(text.lines, head.comment,
                width.cutoff)
            head.comment = grepl("^[[:space:]]*#", text.lines)
        }
        text.lines[head.comment] = sprintf("invisible(\"%s%s%s\")",
            begin.comment, text.lines[head.comment], end.comment)
        blank.line = grepl("^[[:space:]]*$", text.lines)
        if (any(blank.line) && keep.blank.line) {
            else.line = grep("^[[:space:]]*else(\\W|)", text.lines)
            for (i in else.line) {
                j = i - 1
                while (blank.line[j]) {
                  blank.line[j] = FALSE
                  j = j - 1
                  warning("removed blank line ", j, " (you should not put an 'else' in a separate line!)")
                }
            }
            text.lines[blank.line] = sprintf("invisible(\"%s%s\")",
                begin.comment, end.comment)
        }
        text.lines = mask_inline(text.lines)
    } 
    #modified code
    ic=grepl( "%InLiNe_IdEnTiFiEr%", text.lines)
    text.lines[ic]=substr(text.lines[ic], 1, nchar(text.lines[ic])-1)
    text.lines[ic]=  paste0(text.lines[ic], "%InLiNe_IdEnTiFiEr_mod%\"")
    #end modified code
    text.mask = tidy_block(text.lines, width.cutoff, replace.assign)
    text.tidy = if (keep.comment)
        unmask.source(text.mask)
    else text.mask
    text.tidy = reindent_lines(text.tidy, reindent.spaces)
    if (left.brace.newline)
        text.tidy = move_leftbrace(text.tidy, reindent.spaces)
    #modified code
    text.tidy= unlist(sapply(text.tidy, strsplit, "%InLiNe_IdEnTiFiEr_mod%", USE.NAMES=FALSE))
    #end modified code
    if (output)
        cat(paste(text.tidy, collapse = "\n"), "\n", ...)
    invisible(list(text.tidy = text.tidy, text.mask = text.mask))
}     
## ====================================================


## ============ Implementation ============

## Clean-up
if("formatR" %in% loadedNamespaces() ) detach('package:formatR', unload=TRUE)
if(exists("tidy.source"))rm(tidy.source)
library("formatR")


## String with inline comments after arguments
text.input="paste(1 # comm
   ,7)
"     
## The same in vector format
text.input=strsplit(text.input, "\n")[[1]]

## Implementation without patch
tidy.source(text=text.input) #newline removed with  wrong result!
# paste(1  # comm, 7) 


# Tentative patch
unlockBinding("tidy.source", as.environment("package:formatR") )
assign("tidy.source", tidy.source.mod, pos="package:formatR")
environment(tidy.source)= asNamespace( "formatR" )

## Implementation with patch
tidy.source(text=text.input) # apparently ok:
# paste(1  # comm
# , 7) 
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13595145

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档