1

If I have multiple packages loaded that define functions of the same name, is there an easy way to determine which version of the function is currently the active one? Like, lets say I have base R, the tidyverse, and a bunch of time series packages loaded. I'd like a function which_package("intersect") that would tell me the package name of the active version of the intersect function. I know you can go back and look at all the warning messages you recieved when installing packages, but I think that sort of manual search is not only tedious but also error-prone.

There is a function here that does sort of what I want, except it produces a table for all conflicts rather than the value for one function. I would actually be quite happy with that, and would also accept a similar function as an answer, but I have had problems with the implimentation of function given. As applied to my examples, it inserts vast amounts of white space and many duplicates of the package names (e.g. the %>% function shows up with 132 packages listed), making the output hard to read and hard to use. It seems like it should be easy to remove the white space and duplicates, and I have spent considerable time on various approaches that I expected to work but which had no impact on the outcome.

So, for an example of many conflicts:

install.packages(pkg = c("tidyverse", "fpp3", "tsbox", "rugarch", "Quandl", "DREGAR", "dynlm", "zoo", "GGally", "dyn", "ARDL", "bigtime", "BigVAR", "dLagM", "VARshrink")

lapply(x = c("tidyverse", "fable", "tsbox", "rugarch", "Quandl", "DREGAR", "dynlm", "zoo", "GGally", "dyn", "ARDL", "bigtime", "BigVAR", "dLagM", "VARshrink"), 
library, character.only = TRUE)
MrFlick
  • 195,160
  • 17
  • 277
  • 295
andrewH
  • 2,281
  • 2
  • 22
  • 32

1 Answers1

1

You can pull this information with your own function helper.

which_package <- function(fun) {
  if(is.character(fun)) fun <- getFunction(fun)
  stopifnot(is.function(fun))
  x <- environmentName(environment(fun))
  if (!is.null(x)) return(x)
}

This will return R_GlobalEnv for functions that you define in the global environment. There is also the packageName function if you really want to restrict it to packages only. For example

library(MASS)
library(dplyr)
which_package(select)
# [1] "dplyr"
MrFlick
  • 195,160
  • 17
  • 277
  • 295
  • Thanks, MrFlick! I just tried this function on "intersect", which the functionI referenced above reports as defined in tsibble, lubridate, dplyr, and base. I don't think lubridate is loaded by my package set above -- I believe tsibble is by fpp3. But when I run your function on it I got back an empty string "" when the function was passed as a string, and [1] "generics" when I gave it as an unquoted function. – andrewH Jun 17 '21 at 23:39
  • @andrewH This expects the function to be passed is as a unquoted function name. "generics" is where that functions is actually defined. The dplyr version just re-exports that version. Many tidyverse libraries use the "generics" package to define generic methods for base functions that weren't originally defined as generic functions. So that's the function that will actually run so I would say it's working properly. – MrFlick Jun 17 '21 at 23:43
  • Ah! I am embarassed to admit that I did not even kknow there was a package called generics. I just thought it was a function description. I am very happy to have this function, and not just for its obvious utility. It is the first time I have ever used the name of an environment that I didn't name myself. One more baby step toward metaprogramming. – andrewH Jun 18 '21 at 02:17