Search code examples
rconflict

How to handle masking conflicts in R package the right way?


I wonder what the best way to handle masking conflicts the right way if the conflicting packages are not my own packages. Consider the following example. I work a lot with time series and typically function names like quarter, year etc. are used quite often. So if I load tis and data.table the functionality of R clearly depends on the sequence the packages are loaded.

library(tis)
library(data.table)
# this masks: between, month, quarter, year
library(TSfame) # loads TSdbi
con <- TSconnect("somefame.db")
# the following fails when data.table was loaded after tis
ts1 <- TSget("somekeyInYourDB",con)

and TSget from the TSdbi package does not work anymore. Do I need to fork the package and implement some :: syntax? The example might be specific, but the question is pretty general. What would more experienced users do?

EDIT: Probably I need to state this more clearly. The problem is that I don't have a chance to call the function explicitly because TSget is calling the function that should be called explicitly and assumes that there's only tis.

EDIT2, adding the call stack as requested by Richie Cotton:

 Tracing year(actualStart) on entry 
 [[1]]
 TSget("kofbauindikator_total", con)

 [[2]]
  TSget("kofbauindikator_total", con)

 [[3]]
 .local(serIDs, con, ...)

 [[4]]
  getfame(serIDs[i], dbname[i], save = FALSE, envir = parent.frame(), 
  start = NULL, end = NULL, getDoc = FALSE)

  [[5]]
  year(actualStart)

   [[6]]
  .doTrace((function () 
  print(sys.calls()))(), "on entry")

 [[7]]
 eval.parent(exprObj)

 [[8]]
 eval(expr, p)

 [[9]]
 eval(expr, envir, enclos)

 [[10]]
 (function () 
  print(sys.calls()))()

 Error in as.POSIXlt.default(x) : 
    do not know how to convert 'x' to class “POSIXlt”

Solution

  • The call stack shows that the ambiguously named function, year, is called by getfame. getAnywhere("getfame") reveals that this is found in the fame package.

    packageDescription("fame") reveals that fame depends upon tis rather than importing it, which is where the problem lies. As advised here, it's a good idea to email the package maintainer (Jeff Hallman) to request that he change the dependency to an import. That may require a bit of package reworking, so you may also suggest an short-term fix of changing the line

    startYear <- as.integer(year(actualStart))
    

    in getfame to

    startYear <- as.integer(tis::year(actualStart))
    

    (There may be other changes like this necessary.)

    While you await a fix from the maintainer, you could override the function using assignInNamespace. That is, before you load the package, type

    assignInNamespace(
      "getfame", 
      function(sernames, db, connection = NULL, save = FALSE, envir = parent.frame(), 
        start = NULL, end = NULL, getDoc = TRUE) 
      {
        # your fixed function definition with tis::year
      },
      "fame"
    )