代码之家  ›  专栏  ›  技术社区  ›  Duccio A

以编程方式在`::`调用r中切换包

  •  8
  • Duccio A  · 技术社区  · 7 年前

    我想打个电话 bar::foo() ,以便能够以编程方式切换包 bar 所以相同的语法调用 hello::foo() .

    一个例子 :

    • 假设我有三个包裹, parentPkg , childPkg1 childPkg2 .
    • 帕伦特公斤 我有一个函数调用 childPkg1::foo()
    • foo() 也是一个函数 儿童KG2
    • 我想在 帕伦特公斤 使用 :: 要呼叫的操作员 英尺() 但是要通过编程切换包名称。 类似:

      dummy_pkg_name = ifelse(scenario=="child1", "childPkg1", "childPkg2")
      dummy_pkg_name::foo()
      

    有可能吗?我如何实现它?

    某些语境

    帕伦特公斤 是一个与Web应用程序交互、接收一些请求和数据并根据场景返回不同统计模型的结果的函数。
    每个场景都非常复杂,并不是所有的事情都可以概括为 帕伦特公斤 . 因此, 儿童PKG1 儿童KG2 (实际上也有3和4)是处理数据清理的子包,以及每个场景的各种备选方案,但返回相同的值类。
    想法是 帕伦特公斤 将根据场景将包切换到相关的子级,并调用所有必要的函数,而不必为每个子级编写相同的序列,只需使用稍微不同的 :: 打电话。

    3 回复  |  直到 7 年前
        1
  •  12
  •   Julius Vainora    7 年前

    自从 :: 可以看作是一个函数,它看起来像

    `::`(dummy_pkg_name, foo)()
    

    是你想要的。或者,

    getFromNamespace("foo", ns = dummy_pkg_name)()
    

    例如,

    `::`(stats, t.test)
    # function (x, ...) 
    # UseMethod("t.test")
    # <bytecode: 0x102fd4b00>
    # <environment: namespace:stats>
    
    getFromNamespace("t.test", ns = "stats")
    # function (x, ...) 
    # UseMethod("t.test")
    # <bytecode: 0x102fd4b00>
    # <environment: namespace:stats>
    
        2
  •  2
  •   Parfait    7 年前

    坚持 KISS ,只需在全局环境中重新分配新的命名函数。一定要漏掉 () 因为您没有请求运行函数。

    parent_foo <- parentPkg::foo
    child1_foo <- childPkg1::foo
    child2_foo <- childPkg2::foo
    child3_foo <- childPkg3::foo
    

    然后,根据需要有条件地应用它们:

    if (scenario=="child1") {
      obj <- child1_foo(...)
    } 
    else if (scenario=="child2") {
      obj <- child2_foo(...)
    } 
    ...
    
        3
  •  2
  •   Rich Scriven    7 年前

    你也可以创建一个 call() 然后可以对其进行评估。

    call("::", quote(bar), quote(foo()))
    # bar::foo()
    

    投入使用:

    c <- call("::", quote(stats), quote(t.test))
    eval(c)
    # function (x, ...) 
    # UseMethod("t.test")
    # <bytecode: 0x4340988>
    # <environment: namespace:stats>
    

    在函数中使用 setdiff 作为我们的默认功能:

    f <- function(pkg, fn = setdiff) {
        pkg <- substitute(pkg)
        fn <- substitute(fn)
        eval(call("::", pkg, fn))
    }
    
    f(base)
    # function (x, y) 
    # {
    #     x <- as.vector(x)
    #     y <- as.vector(y)
    #     unique(if (length(x) || length(y)) 
    #         x[match(x, y, 0L) == 0L]
    #     else x)
    # }
    # <bytecode: 0x30f1ea8>
    # <environment: namespace:base>
    
    f(dplyr)
    # function (x, y, ...) 
    # UseMethod("setdiff")
    # <environment: namespace:dplyr>