R - 故意屏蔽包函数中的函数?

标签 r

我正在尝试屏蔽包中的函数调用的函数。

作为一个可重现(我认为)的例子,看看函数 isTRUE :

function (x) 
identical(TRUE, x)

假设出于某种原因我想要 identical永远返回 "foobar" ,因此 isTRUE总是会返回“foobar”:
# try override identical
identical <- function(...) { return('foobar') }
identical(TRUE, 'a') # 'foobar', as expected

现在我打电话isTRUE ,希望调用identical在该函数中将访问我的屏蔽版本,但它不会:
isTRUE('a') # hope that this will return 'foobar'
# [1] FALSE

所以一般来说,我如何暂时导致从打包函数中调用的函数返回不同的东西?

语境

我的包中有一个函数:
myFunc <- function(...) {
    if (!require(rgdal)) {
        stop("You do not have rgdal installed")
    }
    # ...
}

我想测试一下,如果没有安装 rgdal,该函数会抛出错误。
但是,我确实安装了 rgdal。我要 myFunc认为它不是(暂时),所以我试图做:
require <- function(...) { return(FALSE) }

调用前 myFunc希望它会失败。然而,似乎myFunc没有被这个欺骗,仍然打电话 base::require而不是我的 require .

(是的,这似乎是一件微不足道的事情,因为如果我没有安装 rgdal,myFunc 肯定会抛出错误,但假设现在条件更复杂,我想以相同的方式进行测试 - 我的问题仍然存在站立)

最佳答案

您可以以编程方式创建一个函数

foo <- function(...) if(!require('MASS')) stop('foo')

testfun <- function(fun){
  require <- function(...) FALSE
  fff <- function(){}
    formals(fff) <- formals(fun)
    body(fff) <- body(fun)
  fff

}

testfoo <- testfun('foo')
require定义为 testfun现在创建函数时。
foo()
## Loading required package: MASS

detach(package:MASS)

testfoo()
# Error in testfoo() : foo

你可以用 local 做类似的事情,但我认为它会更困惑

例如
testfoo2 <- local({
  require <- function(...) FALSE
  foo <- function(...) if(!require('MASS')) stop('foo')
  })

testfoo2()
## Error in testfoo2() : foo

(来自数学咖啡 - 基于此答案的后续行动)。

我能够定义一个函数:
overrideIn <- function(f, ...) {                                                
    overrides <- list(...)                                                      
    nms <- names(overrides)[names(overrides) != '']                             
    # stub out the functions                                                    
    for (nm in nms) {                                                           
        assign(nm, overrides[[nm]])                                             
    }                                                                           

    # copy over f                                                               
    fff <- function () {}                                                       
    formals(fff) <- formals(f)                                                  
    body(fff) <- body(f)                                                        
    return(fff)                                                                 
}

这样我就可以做
f <- overrideIn(myFunc, require=function (...) FALSE)

现在当我打电话时 f它具有 require 的覆盖版本在里面,所以我可以做(使用梦幻般的 testthat 包):
expect_that(f(), throws_error('You do not have rgdal installed'))

一个稍微简洁的 overide 函数版本(再次是 mnel)
overRideIn2 <- function(fun,...){
   e <- environment()
   .list <- list(...)
   ns <- nchar(names(.list))>0L

   list2env(.list[ns], envir = e) 

   fff <- as.function(as.list(fun))

  }

关于R - 故意屏蔽包函数中的函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15262084/

相关文章:

r - 比较多行并在 R 或 Excel 中创建矩阵

r - 为 facet_wrap (ggplot2) 中的每个图指定不同的 xlim

r - 加载 namespace 'plotp'时未找到对象 'rms'

r - 如何使用 rmongodb 将数据帧插入到 mongodb

R : C++11 standard requested but CXX11 is not defined

r - 将行分成 10 组,每组具有相同的值

r - 如何计算R中的多列

R中的回归树

r - 使用 R 进行 K 中心聚类 - 结果图是否正确?

r - 以其他列为条件向数据框列添加常量