【问题标题】:Referring to package and function as arguments in another function将包和函数称为另一个函数中的参数
【发布时间】:2019-10-18 14:24:22
【问题描述】:

我正在尝试在 R 中的不同包中查找特定函数的方法。例如,methods(broom::tidy) 将返回包 broom 中函数 tidy 的所有方法。对于我当前的问题,如果我可以在另一个函数中使用 methods 函数会更好,如下所示: f1 <- function(x,y){ methods(x::y) }

(我删除了与我的问题无关的其他代码部分。) 但是,当我像这样运行函数时:

f1 <- function(x,y){ methods(x::y)}
f1(broom,tidy)

我得到了错误

loadNamespace(name) 中的错误:没有名为“x”的包

如果我尝试将其修改为仅更改功能但保持包相同,我会收到类似的错误:

f2 <- function(y){  methods(broom::y)}
f2(tidy)

错误:'y' 不是从 'namespace:broom' 导出的对象

如何让包和函数名称在函数中正确评估?当前的问题是否与r 尝试评估/替换函数中的值有关?

【问题讨论】:

    标签: r function


    【解决方案1】:

    ::methods() 函数都使用非标准评估才能工作。这意味着您需要更聪明地向函数传递值才能使其工作。这是一种方法

    f1 <- function(x,y){ 
      do.call("methods", list(substitute(x::y)))
    }
    f1(broom,tidy)
    

    在这里,我们使用substitute() 来扩展并将xy 值传入命名空间查找。这解决了您可以看到的:: 部分

    f2 <- function(x,y){ 
      substitute(x::y)
    }
    f2(broom,tidy)
    # broom::tidy
    

    我们需要替代品,因为很可能有一个包x 和函数y。因此,使用:: 时不会扩展变量。请注意,:: 只是 getExportedValue() 的包装器,否则您需要使用字符值从命名空间中提取值。

    但还有另一个问题:methods() 不评估它的参数,它使用原始表达式来查找方法。这意味着我们实际上并不需要broom::tidy 的值,我们可以传递该文字表达式。由于我们需要评估替换来获得我们需要的表达式,因此我们需要使用do.call() 构建调用以评估substitute 并将该表达式传递给methods()

    【讨论】:

    • 如何将f2(dplyr, between) 转换为函数?它返回未评估的函数调用。类似于`f2(dplyr, between)(1,2,3)
    • @slava-kohut。好吧,你可以直接调用`::`(dplyr, between)(1,2,3) 或者你可以eval() 表达式eval(f2(dplyr, between))(1,2,3)
    • 后者是我问的。谢谢!
    • @MrFlick random 但有纯rlang 解决方案吗?我试图用enexprenquo 替换substitute,但得到arg 必须是符号的错误。我最初认为substituterlang 中的enexpr 相同,但我现在意识到substitute 可能具有更多功能。
    • @Mike 这是我可以让它为 rlang 工作的唯一方法:f3 &lt;- function(x,y){ x &lt;- rlang::ensym(x); y &lt;- rlang::ensym(y);rlang::eval_tidy(rlang::quo(methods(::(!!x, !!y))))} :: 运算符的解析似乎有点古怪。
    猜你喜欢
    • 2018-07-30
    • 2019-03-05
    • 1970-01-01
    • 2019-10-09
    • 2022-01-11
    • 2017-08-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多