Dear list I'm not sure whether this is a bug or an unavoidable consequence of the way packages are loaded, but there can be surprising side effects of calling a function via package::function. Here's an example using the formula.tools package: form <- a ~ b as.character(form) formula.tools::lhs(form) as.character(form) The first call to as.character returns: [1] "~" "a" "b" The second returns: [1] "a ~ b" The reason being that formula.tools has: S3method(as.character,formula) in its namespace, which quietly supersedes the default one. In my case it led to a bug that was rather hard to track down because it looked like non-deterministic behaviour. Shouldn't there at least be a warning about such side effects, the way library() tells you about masking? Best Simon Barthelme
A package should probably never register a S3 method unless it owns either the generic or the class. Here `formula.tools` owns neither. Instead of registering the method, it should export it like a regular function. This way S3 dispatch is based on lexical scoping rather than session-wide side effect. Lionel> On 1 sept. 2017, at 12:57, Simon Barthelm? <simon.barthelme at gipsa-lab.fr> wrote: > > Dear list > > I'm not sure whether this is a bug or an unavoidable consequence of the way packages are loaded, but there can be surprising side effects of calling a function via package::function. Here's an example using the formula.tools package: > > form <- a ~ b > as.character(form) > formula.tools::lhs(form) > as.character(form) > > The first call to as.character returns: > [1] "~" "a" "b" > The second returns: > [1] "a ~ b" > > The reason being that formula.tools has: > S3method(as.character,formula) > in its namespace, which quietly supersedes the default one. In my case it led to a bug that was rather hard to track down because it looked like non-deterministic behaviour. > Shouldn't there at least be a warning about such side effects, the way library() tells you about masking? > > Best > > Simon Barthelme > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel
>>>>> Simon Barthelm? <simon.barthelme at gipsa-lab.fr> >>>>> on Fri, 1 Sep 2017 12:57:13 +0200 writes:> Dear list > I'm not sure whether this is a bug or an unavoidable consequence of the > way packages are loaded, but there can be surprising side effects of > calling a function via package::function. Here's an example using the > formula.tools package: > form <- a ~ b > as.character(form) > formula.tools::lhs(form) > as.character(form) > The first call to as.character returns: > [1] "~" "a" "b" > The second returns: > [1] "a ~ b" > The reason being that formula.tools has: > S3method(as.character,formula) > in its namespace, which quietly supersedes the default one. Sure. > In my case it led to a bug that was rather hard to track > down because it looked like non-deterministic behaviour. well, it shouldn't have been hard to track I think ... see below > Shouldn't there at least be a warning about such side effects, the way > library() tells you about masking? The help page on "::" is pretty clear about the fact that the namespace is loaded if necessary. Personally I've got the impression that <namespace>::<name> is much "overused" nowadays, notably in packages where I'd strongly advocate using importFrom() in NAMESPACE, so all this happens at package load time, and then _not_ using `::` in the package sources itself. Many people seem to forget that every use of `::` is an R function call and using it is ineffecient compared to just using the already imported name. Best, Martin Maechler ETH Zurich and R Core Team > Best > Simon Barthelme
>>>>> Lionel Henry <lionel at rstudio.com> >>>>> on Fri, 1 Sep 2017 13:47:07 +0200 writes:> A package should probably never register a S3 method unless it owns > either the generic or the class. I agree... (and typically it does "own" the class) > Here `formula.tools` owns neither. i.e., it neither defines as.character() nor class "formula". > Instead of registering the method, it should export it like a regular > function. This way S3 dispatch is based on lexical scoping rather than > session-wide side effect. I don't the 2nd sentence above is quite correct. S3 method registration should be done (in the case it should) and S3 dispatch is not just based on lexical scoping but also on S3 method registration. > Lionel It is still the case that :: silently loads the namespace if needed, and that "things may behave differently" after the use '::', because loading a namespace does have an effect on the R session ..., (and I still think `::` is much "over used") Martin >> On 1 sept. 2017, at 12:57, Simon Barthelm? <simon.barthelme at gipsa-lab.fr> wrote: >> >> Dear list >> >> I'm not sure whether this is a bug or an unavoidable consequence of the way packages are loaded, but there can be surprising side effects of calling a function via package::function. Here's an example using the formula.tools package: >> >> form <- a ~ b >> as.character(form) >> formula.tools::lhs(form) >> as.character(form) >> >> The first call to as.character returns: >> [1] "~" "a" "b" >> The second returns: >> [1] "a ~ b" >> >> The reason being that formula.tools has: >> S3method(as.character,formula) >> in its namespace, which quietly supersedes the default one. In my case it led to a bug that was rather hard to track down because it looked like non-deterministic behaviour. >> Shouldn't there at least be a warning about such side effects, the way library() tells you about masking? >> >> Best >> >> Simon Barthelme >> >> ______________________________________________ >> R-devel at r-project.org mailing list >> https://stat.ethz.ch/mailman/listinfo/r-devel > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel