[Rd] Problems with ::

@vi@e@gross m@iii@g oii gm@ii@com @vi@e@gross m@iii@g oii gm@ii@com
Wed Mar 19 19:52:51 CET 2025


Terry,

If I understand you, this is a problem anytime you include more than one
function with the same name and the latest masks all others. It is not only
a problem with the tidyverse, albeit that is an example of bringing in quite
a few functions from many packages at once.

I wonder if the following work-around makes some sense or will just cause
more issues somewhere.

Your concern is that if the user asks for something like package::function
it can cause issues. You are exploring options but I wonder if t can be
handled somewhat by the caller not using that.

Consider a function like stats::filter which is often masked by
dplyr::filter. If I ask for help on "filter" BEFORE loading tidyverse, I see
the stats version and can use it. After loading, the dplyr version is used
and the help shows both as it looks.

But when I add the line: 

filter <- stats::filter

I can reset it so the proper function is called. If you need both, you can
do something like this:

statsfilter <- stats::filter

The point is when calling another function such as your example, the
"package::" need not be passed along and all the other side would see is
"filter" which it would evaluate in an environment that hopefully now works
properly. 

In your case, would the following change work?

workaround_cluster<- survival::cluster

And then use "workaround_cluster" to avoid the confusion you need.

This is not a SOLUTION in any real sense but if it works, could be helpful
to some. Assuming dplyr has no compatibility, you can then use dplyr::filter
when you want the other one or ...

-----Original Message-----
From: R-devel <r-devel-bounces using r-project.org> On Behalf Of Therneau, Terry
M., Ph.D. via R-devel
Sent: Wednesday, March 19, 2025 12:50 PM
To: r-devel using r-project.org
Subject: [Rd] Problems with ::

In response to the tidyverse habit of adding another zillion functions to
one's search space, the use of things like survival::coxph is becoming more
common.  But this practice breaks the use of the specials argument in
terms.formula, something that I make heavy use of in the survival package.
The following two pairs of models give different answers, and the second is
wrong.

fit1a <- lm(GNP ~  Year + offset(Unemployed), longley)
fit1b<- lm(GNP ~  Year + stats::offset(Unemployed), longley)

fit1a <- survdiff(Surv(time, status) ~ rx + cluster(litter), rats)
fit1b <- survdiff(Surv(time, status) ~ rx + survival::cluster(litter), rats)
zed <- survival::cluster(rats$litter)
fit1c <- survdiff(Surv(time, status) ~ rx + zed, rats)

In the most recent CRAN version of survival I added some pre-processing
steps that successfully catch fit1b, by stripping off  "survival::" from
formulas before calling terms.formula.   But I can't prevent fit1c, and
don't yet know if there are other case not covered by my current hack.  At
least one of the CRAN packages that depends on survival has an example of
exactly fit1c in their test suite.

The survival package uses the special argument a lot: strata, cluster,
pspline, tt, frailty, and ridge.  I'm trying to think of a good plan for
long term changes.   I list 3 below, and am hoping for better ideas or
input.

a. Caveat emptor:  If you work hard to fool the specials argument, and
succeed, then "Congratulations, you fooled the parser."

b. What I did early on with tt(), which is to make the function defition
completely internal to coxph (the only survival function that uses tt).
People who type survival::tt or  survival:::tt get an error message.   A
plus of this is that the error message will  wean users from pasting
survival:: to everything inside a formula.   The disadvantages are first
that it will break existing user code (most of which should be broken -- its
not doing what they think), a second is that there may be use cases for
strata, say, outside of a survival formula; it is essentially factor with
shorter default labels.

c. Make all of these functions have a class, and rewrite the code to depend
on the class rather than specials.  The Surv function is recognized in this
way, so is not harmed by survival::Surv.  It is also why calling Surv to
create a new variable is fine.  I'd still retain specials,  to support
legacy code.

The more ornery part of me votes for b (what is the effect on help files)?
In any case a change won't happen overnight.
Do we leave offset in the caveat emptor group?
A small section needs to be added to the "user written packages" document,
where it talks about specials.
What other packages use specials?

Terry T.







	[[alternative HTML version deleted]]

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



More information about the R-devel mailing list