My package's DESCRIPTION
file has httr
in its Imports directive:
Imports:
httr (>= 1.1.0),
jsonlite,
rstudioapi
httr
exports an S3method for length.path
.
S3method(length,path)
And it's defined as:
#' @export
length.path <- function(x) file.info(x)$size
In my package I have objects that I assign the class "path" to. Every time I assign the class "path" to any object, regardless of whether or not I ever call length()
on the object, this is printed to stdout:
Error in file.info(x) : invalid filename argument
Here's some reproducible code everyone can run:
> sessionInfo()
R version 3.3.1 (2016-06-21)
Platform: x86_64-apple-darwin13.4.0 (64-bit)
Running under: OS X 10.11.5 (El Capitan)
locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
attached base packages:
[1] stats graphics grDevices utils datasets methods base
loaded via a namespace (and not attached):
[1] tools_3.3.1
> thing = 1:5
> class(thing) = 'path'
> requireNamespace('httr')
Loading required namespace: httr
> sessionInfo()
R version 3.3.1 (2016-06-21)
Platform: x86_64-apple-darwin13.4.0 (64-bit)
Running under: OS X 10.11.5 (El Capitan)
locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
attached base packages:
[1] stats graphics grDevices utils datasets methods base
loaded via a namespace (and not attached):
[1] httr_1.2.1 R6_2.1.2 tools_3.3.1
> thing = 1:5
> class(thing) = 'path'
Error in file.info(x) : invalid filename argument
I've tried catching it in a try
but that doesn't work:
set_class = function(obj, c) {
class(obj) = c
return(obj)
}
thing = 1:5
thing = try(set_class(thing, 'path'), silent=TRUE)
Yields:
Error in file.info(x) : invalid filename argument
I've tried assignInNamespace
to override the function:
base_length = function(obj) {
return(base::length(obj))
}
assignInNamespace('length.path', base_length, 'httr')
thing = 1:5
class(thing) = 'path'
But I get Error: evaluation nested too deeply: infinite recursion / options(expressions=)?
When I use httr
functions in my package I use them with httr::function
so I'm not sure how this length.path
function is leaking into my namespace and overriding the base length function. I've also tried explicit @importFrom httr function
for each function that I use instead of using httr::function
but that doesn't work either.
I also found this:
https://support.bioconductor.org/p/79059/
But the solution seemed to be to edit the source code of httr
, which I can't do since my package imports it. How can I get around this?
If your package users rely on an internal function that you decide to ditch when re-factoring code, they won’t be happy, so only export what you want to maintain. If all packages exposed all their internal functions, the user environment would be flooded and the namespace conflicts would be out of control. Why write internal functions?
When writing R code in general there are several reasons to write functions and it is the same within R packages: you can re-use a bit of code in several places (e.g. an epoch converter used for the output of several endpoints from a web API), and you can give it a self-explaining name (e.g.
An R package can be viewed as a set of functions, of which only a part are exposed to the user. In this blog post we shall concentrate of the functions that are not exposed to the user, so called internal functions: what are they, how does one handle them in one’s own package, and how can one explore them? What is an internal function?
One possibility could be to create a function length.path()
in your own package. If the base type of your path
-objects is compatible with base::length()
you could just unclass it to avoid infinite recursion:
length.path <- function(x) length(unclass(x))
However, this is potentially slow compared to a direct call to base::length()
because it copies the object and needs method dispatch two times.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With