[Rd] [External] DOCS/BUG?: opts <- base::.Options is *not* a copy
iuke-tier@ey m@iii@g oii uiow@@edu
iuke-tier@ey m@iii@g oii uiow@@edu
Fri Feb 25 14:13:03 CET 2022
On Fri, 25 Feb 2022, Martin Maechler wrote:
>>>>>> Henrik Bengtsson
>>>>>> on Thu, 24 Feb 2022 11:21:05 -0800 writes:
>
> > On Thu, Feb 24, 2022 at 5:23 AM <luke-tierney using uiowa.edu> wrote:
> >>
> >> On Thu, 24 Feb 2022, Henrik Bengtsson wrote:
> >>
> >> > Hi, is the following a non-documented feature or a bug:
> >> >
> >> > $ R --quiet --vanilla
> >> > opts <- base::.Options
> >> > opts[["abc"]]
> >> > #> NULL
> >> > options(abc = 42)
> >> > opts[["abc"]]
> >> > #> [1] 42
> >> >
> >> > I would have expected that 'opts' would be a *copy* of base::.Options
> >> > that is not affected by later changes to base::.Options. FWIW, the
> >> > same happens if we try with:
> >> >
> >> > opts <- .BaseNamespaceEnv[[".Options"]]
> >> >
> >> > I don't think lazy evaluation is involved, because I evaluate
> >> > opts[["abc"]] above.
> >> >
> >> > The only thing help(".Options") says is:
> >> >
> >> > Note:
> >> > For compatibility with S there is a visible object .Options whose
> >> > value is a pairlist containing the current options() (in no particular
> >> > order). Assigning to it will make a local copy and not change the
> >> > original. (Using it however is faster than calling options()).
> >>
> >> You are misreading what this says. As with any assignment to an object
> >> that has other references, the assignment will create a local copy
> >> before mutating.
>
> > I don't think I misread it; that's exactly how I interpreted it, too.
> > I just copied that passage to help the reader see that there's nothing
> > in the docs mentioning this behavior.
>
> >> It does not say that referencing the object makes a
> >> copy. So there is no inconsistency.
>
> > I'd argue that this behavior of .Options (because of how options() is
> > implemented) is not a standard procedure in R, and that the
> > expectation would be to make a copy unless otherwise documented. You
> > need to dig into the code to figure out that this is not the case and
> > how it works. For example, my mental model of how this is implemented
> > is something like:
>
> > .Options <- pairlist()
> > options <- function(...) {
> > args <- list(...)
> > old <- new <- .Options
> > for (name in names(args)) new[[name]] <- args[[name]]
> > assignInMyNamespace(".Options", new)
> > invisible(old)
> > }
>
> > and that does create a copy.
>
> > I only discovered this because I added the following to my package tests:
>
> > opts <- base::.Options
> > call_random_fcn()
> > stopifnot(identical(base::.Options, opts))
>
> > Turns out it never failed. I use .Options, because it's faster than
> > options(), which always sorts elements by their names. FWIW, the
> > workaround is to force a copy using opts <- as.list(base::.Options).
>
> Esthetics only: I think I'd rather use
>
> opts <- force(base::.Options)
This doesn't create a copy (you cha check with .Internal(inspect()).
Using as.list creates a VECSXP, which is better anyway as we are
trying to reduce the use of pairlists at R revel.
>
>
> >> That options() modifies the value of an object with multiple
> >> references is not ideal, but changing that while maintaining .Object
> >> as a regular variable is probably more trouble than it is worth. It is
> >> probably time to work towards deprecating .Options (maybe turning it
> >> into an active binding that does make a copy). At the very least
> >> discouraging its use in the help file.
>
> > This sounds good to me.
>
> We might consider `options()` gaining an optional argument, say
> `sortNames = TRUE` and `options(sortNames=FALSE)` would still not
> sort and hence be faster than pure options()
Please don't. Whether or not there is some sorting going on somewhere
is not something a user should have to worry about. I certainly would
not want to have to think about it. If there really is a performance
issue, and that case has not been made, then that can be looked into.
Deprecating .Options is worth considering in principle; converting to
an active binding that converts the internal pairlist to vector list
is also worth considering in principle, but again I don't see this as
having high priority.
Best,
luke
>
> Martin
>
>
>
> > Thanks,
>
> > Henrik
>
> >>
> >> Other that changing the docs I doubt this will ever get high enough on
> >> anyone's priority list to get done
> >>
> >> Best,
> >>
> >> luke
> >>
> >> >
> >> > This behavior goes back to at least R 2.15.0.
> >> >
> >> > /Henrik
> >> >
> >> > ______________________________________________
> >> > R-devel using r-project.org mailing list
> >> > https://stat.ethz.ch/mailman/listinfo/r-devel
> >> >
> >>
> >> --
> >> Luke Tierney
> >> Ralph E. Wareham Professor of Mathematical Sciences
> >> University of Iowa Phone: 319-335-3386
> >> Department of Statistics and Fax: 319-335-3017
> >> Actuarial Science
> >> 241 Schaeffer Hall email: luke-tierney using uiowa.edu
> >> Iowa City, IA 52242 WWW: http://www.stat.uiowa.edu
>
> > ______________________________________________
> > R-devel using r-project.org mailing list
> > https://stat.ethz.ch/mailman/listinfo/r-devel
>
> ______________________________________________
> R-devel using r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>
--
Luke Tierney
Ralph E. Wareham Professor of Mathematical Sciences
University of Iowa Phone: 319-335-3386
Department of Statistics and Fax: 319-335-3017
Actuarial Science
241 Schaeffer Hall email: luke-tierney using uiowa.edu
Iowa City, IA 52242 WWW: http://www.stat.uiowa.edu
More information about the R-devel
mailing list