【问题标题】:Using call() with namespace address (:: or :::)将 call() 与命名空间地址(:: 或 :::)一起使用
【发布时间】:2017-10-27 12:40:45
【问题描述】:

我在将call() 函数与命名空间地址运算符::::: 一起使用时遇到问题。只需将其添加到为 call() 提供的函数名称中,就会在评估调用时产生错误,正如这个愚蠢的示例所示:

> call("base::print", "Hi there")
`base::print`("Hi there")
> eval(call("base::print", "Hi there"))
Error in `base::print`("Hi there") : 
 could not find function "base::print"

出于某种原因,call() 在函数名周围添加了反引号(可能是因为它包含非标准字符),这似乎把一切都搞砸了。以下是省略“地址”时会发生的情况:

> call("print", "Hi there")
print("Hi there")
> eval(call("print", "Hi there"))
[1] "Hi there"

我将非常感谢有关如何解决此问题的任何建议。但是请注意,我需要使用call() 生成代码,因为我正在为 rmarkdown 代码块自动生成代码,并且我需要能够指定命名空间,因为我正在使用我的包中未导出的函数,我真的很喜欢保持不出口。

感谢阅读!


更新:我忽略了我正在寻找的解决方案的另一个属性(通过阅读下面的 Stéphane Laurent 的其他很好的答案,我意识到了这一点):我正在寻找一个不将函数定义复制到调用中的解决方案,我认为这排除了使用get() 的解决方案。作为我试图避免的一个例子,假设我们想从ggplot2 调用qplot()。如果我们使用例如getFromNamespace() 调用将如下所示(为了便于阅读,省略了输出的中间部分):

> as.call(list(getFromNamespace("qplot", "ggplot2"), 1:10))

  (function (x, y = NULL, ..., data, facets = NULL, margins = FALSE, 
  geom = "auto", xlim = c(NA, NA), ylim = c(NA, NA), log = "", 
  main = NULL, xlab = deparse(substitute(x)), ylab = deparse(substitute(y)), 
asp = NA, stat = NULL, position = NULL) 
{
  if (!missing(stat)) 
      warning("`stat` is deprecated", call. = FALSE)
  if (!missing(position)) 
      warning("`position` is deprecated", call. = FALSE)
  if (!is.character(geom)) 
      stop("`geom` must be a character vector", call. = FALSE)
  argnames <- names(as.list(match.call(expand.dots = FALSE)[-1]))
  arguments <- as.list(match.call()[-1])
  env <- parent.frame()

#### A lot more code defining the function (omitted)#####

  if (!missing(xlim)) 
      p <- p + xlim(xlim)
  if (!missing(ylim)) 
      p <- p + ylim(ylim)
  p
})(1:10)

如果我们改为使用as.call(list(ggplot2::qplot, 1:10)),也会发生同样的事情。

我正在寻找的是产生调用ggplot2::qplot(1:10) 的东西。

【问题讨论】:

    标签: r


    【解决方案1】:

    也许

    > eval(as.call(list(getFromNamespace("print", "base"), "Hi there")))
    [1] "Hi there"
    

    【讨论】:

    • 虽然对于大多数有经验的 R 用户来说很明显为什么这个解决方案有效,但最好包含一个简短的描述来让经验不足的用户学习。
    • 谢谢,我不知道getFromNamespace()。这工作得很好,但函数定义中的调用副本。你知道这是否可以避免吗?在我的设置中,这种复制将意味着大量额外的代码行,因为我有时需要调用未导出的函数,例如在同一个 rmarkdown 文档中 100 次。
    • @AHP 不确定是否理解。其实你也可以eval(as.call(list(base::print, "Hi there"))).
    • @StéphaneLaurent 抱歉,我意识到我的评论不太清楚。我已尝试在问题的更新中对其进行解释 - 我希望这可以使其更清楚。
    猜你喜欢
    • 1970-01-01
    • 2012-01-11
    • 2016-09-14
    • 2021-08-26
    • 1970-01-01
    • 2014-10-13
    • 2016-10-31
    • 2016-04-23
    • 2018-06-14
    相关资源
    最近更新 更多