通过从先前加载的包

时间:2017-01-22 01:53:29

标签: r ggplot2

在我的包中,我将%+%运算符定义为字符串连接的快捷方式。由于它可能由以前加载的包定义,我只想在两个参数都合适时(例如字符)执行我的自定义代码,否则尝试从先前加载的包中调用代码。这是我的解决方案:

# helper function to find environment of the package
getEnvByName <- function(inpEnv=.GlobalEnv, lookFor){
  e <- inpEnv;
  while (environmentName(e) != 'R_EmptyEnv' & environmentName(e)!=lookFor) e <- parent.env(e);
  if (environmentName(e) != lookFor) return(NULL);
  return(e);
}

"%+%" <- function(arg1, arg2){
  if (is.character(arg1) & is.character(arg2)) {
    paste0(arg1, arg2);
  } else {
    e <- parent.env(getEnvByName(.GlobalEnv,'package:mypackagename'));
    if (exists('%+%', envir = e)) get('%+%',envir = e)(arg1,arg2);
  } 
}

我的问题是:
1)这是处理这种情况的好方法吗? 2)为什么在其他包装中做类似的事情不常见?例如,在ggplot2包中,%+%运算符定义如下:

"%+%" <- function (e1, e2) 
{
    e2name <- deparse(substitute(e2))
    if (is.theme(e1)) add_theme(e1, e2, e2name)
    else if (is.ggplot(e1)) add_ggplot(e1, e2, e2name)
}

如您所见,他们的代码中断了先前为任何参数定义的%+%,而他们只能为themeggplot参数覆盖它并保留所有其他情况。我可以建议作者实施这种检查,但我认为他们没有这样做的原因......

UPD。只是对我的代码进行了一些修改:我没有在一个函数中定义所有内容,而是将其与UseMethod()分开 - 我想知道它是否有任何区别:

`%+%` <- function(...) UseMethod("%+%")
`%+%.character` <- paste0
`%+%.default` <- function (arg1, arg2){
  e <- parent.env(getEnvByName(.GlobalEnv,'package:mypackagename'));
  get('%+%',envir = e)(arg1,arg2);
}

1 个答案:

答案 0 :(得分:1)

首先,我认为重新实现已广泛使用的软件包中已存在的函数是一种很好的做法(我在前面提到%s+%来自stringi)。

关于你的问题,我认为最好的方法是:

'%+%' <- function(arg1, arg2){
  if (is.character(arg1) & is.character(arg2)) {
    paste0(arg1, arg2)
  } else {
    old.func <- get('%+%',
                    envir = parent.env(.GlobalEnv),
                    inherits = TRUE)
    old.func(arg1, arg2)
  } 
}
  1. 使用选项inherits = TRUE(默认情况下)get在您的答案中实施的环境中执行相同的搜索;
  2. 使用UseMethod的方法将以不同的方式工作,因为在这种情况下%+%将仅检查类型&#34;字符&#34;的第一个参数,而不是两个参数;
  3. 关于ggplot2 s %+%我认为它的目的是让NULL返回不合适的参数&#39;类型。它可能是代码中的一个缺陷。