1

I think this is a simple question, and the answer is probably somewhere in either Hadley's book or the official R documentation, or in the answers to Writing robust R code: namespaces, masking and using the `::` operator, but I haven't come across it yet (or don't remember reading about it).

Let's say I want to write a package that contains the function:

sort_by_column <- function(x, j) {
  j_ord <- order(x[, j])
  x[j_ord, ]
}

If I define this function in the global environment and I pass in a value for x that is a data.table, it will silently fail because [ will dispatch to [.data.table instead of [.data.frame:

library(data.table)
sort_by_column(iris, 3)
sort_by_column(data.table(iris), 3)

My gut tells me that [.data.table won't even be available to my package unless I explicitly import it, in which case this problem can't occur in a package the way it can occur in the global environment. Is that true? If not, how can I handle this kind of masking?

edit 2: Function sort_by_column is defined in package A. Another package, B was loaded before package A but is not explictly imported by A. Do calls from functions defined in A search in package B?

edit: To clarify, I want to define a function inside a package in such a way that it "ignores" other packages the user might have loaded, in order to avoid function naming conflicts like the one demonstrated above. Is this ignoring behavior automatic, or do I need to do something in particular?

Community
  • 1
  • 1
shadowtalker
  • 12,529
  • 3
  • 53
  • 96
  • If your function in the package or the global or both? – csgillespie Sep 12 '15 at 19:47
  • @csgillespie it's in the package. I was just using the global scope to demonstrate the problem. – shadowtalker Sep 13 '15 at 00:33
  • `[` being generic, it will look at the class of the object. If it's a data.table, it will try to call a `[.data.table`. If that's what you want to happen, you should import it explicitly in DESCRIPTION and NAMESPACE. If you haven't done so, `[` will search for a `[.data.table` method on the user's search path, in which case unpredictable results may occur. If the search path doesn't have any corresponding `data.table` method, it will default to the `data.frame` one (since `data.table` inherits from `data.frame`) – baptiste Sep 13 '15 at 01:20
  • @baptiste I want that to _not_ happen. See my edit in bold – shadowtalker Sep 13 '15 at 01:29
  • then use DWin's answer below, bypassing the class check with `[.data.frame`. You may want to rename it for clarity, e.g. `get_col <- function(x, j) base::"[.data.frame"(x, TRUE, j)`. Alternatively, use `as.data.frame` before anything in your function. – baptiste Sep 13 '15 at 01:38

1 Answers1

2

If you want to specify a particular method for "[" then you should be able to use:

 `[.data.frame`(x, TRUE, j)

Or test for data.tables using inherits and trap that as an edge case?

IRTFM
  • 258,963
  • 21
  • 364
  • 487