On 05/30/2014 10:00 AM, Hadley Wickham wrote:
There is at least one subtle consequence to keep in mind when doing
this. Of course, whatever choice you make, if the whatever() function
moves to a different package, this breaks your package.
However, if you explicitly import the function, your package will
break at load-time (which is good) and you'll only have to modify
1 line in the NAMESPACE file to fix it. But if you do foo::whatever(),
your package won't break at load-time, only at run-time. Also you'll
have to edit all the calls to foo::whatever() to fix the package.

Probably not a big deal, but in an environment like Bioconductor where
infrastructure classes and functions can be shared by hundreds of
packages, having people use foo::whatever() in a systematic way would
probably make maintenance a little bit more painful than it needs to
be when the need arises to reorganize/refactor parts of the
infrastructure. Also, the ability to quickly grep the NAMESPACE
files of all BioC packages to see who imports what is very convenient
in this situation.

OTOH, I think there's a big benefit to being able to read package code
and instantly know where a function comes from.

To me this is way more readable:

  setClass("A", representation(...))
  setMethod("head", "A", function(x, ...) {...})

than this:

  methods::setClass("A", methods::representation(...))
  methods::setMethod(utils::head, "A", function(x, ...) {...})

All the :: clutter adds very little value and hurts readability.
Just a matter of taste I guess.

Also it almost never matters to me *where* a function comes from.
The only thing I find relevant when I read code is *what* a function
does and I can find out by doing ?whatever (I generally don't need
to do ?foo::whatever). If I need to try it (interactively), I do
whatever(...), not foo::whatever(...). Sometimes, ?whatever will
fail because foo's NAMESPACE is loaded but foo is not attached to my
search path. In that case, and in that case only, I need to know
*where* the function comes from so I can library() the package where
it's defined and documented, and then I can do ?whatever. But this is
a rare situation and doesn't justify systematic use of foo::whatever().

So I only reserve the use of foo::whatever() to disambiguate in case
of name collision or to call a function defined in a *suggested*
package.

Finally, now that the use of a NAMESPACE became mandatory (well, this
happened a few years ago), advocating systematic use of foo::whatever()
without explicitly importing the function sounds a little bit like an
heroic act of resistance ;-)

H.


Personally, I found this outweighs the benefits that you outline:

* functions rarely move between packages, and gsubbing for pkga:foo to
pkgb:foo isn't hard
* it's not that much hard to grep for pkg::foo in R/* than it is to
grep NAMESPACE

Hadley


--
Hervé Pagès

Program in Computational Biology
Division of Public Health Sciences
Fred Hutchinson Cancer Research Center
1100 Fairview Ave. N, M1-B514
P.O. Box 19024
Seattle, WA 98109-1024

E-mail: hpa...@fhcrc.org
Phone:  (206) 667-5791
Fax:    (206) 667-1319

______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel

Reply via email to