This is sort of the strangest thing I ever encountered in R.
Is it possible, that certain argument names (lazy
in my case) are special/reserved and thus would lead to unexpected behavior when a calling stack is involved that spreads across functions of three different packages: optionr::setAnywhereOptions()
calls nestr::setNested()
calls reactr::setShinyReactive()
?
Consider the following example/situation (also described in this GitHub issue)
Adapted from this unit test in package optionr
require("devtools")
devtools::install_github("Rappster/conditionr")
devtools::install_github("Rappster/typr")
devtools::install_github("Rappster/nestr")
devtools::install_github("Rappster/reactr", ref = "bug-28")
devtools::install_github("Rappster/optionr")
require("optionr")
path <- file.path(tempdir(), "test")
create(path, description = getOption("devtools.desc"), check = FALSE,
rstudio = TRUE)
setwd(path)
container <- initializeOptionContainer(overwrite = TRUE)
setAnywhereOption(id = "x_1", value = TRUE, reactive = TRUE)
getAnywhereOption(id = "x_1")
setAnywhereOption(id = "x_2",
value = reactr::reactiveExpression(
!getAnywhereOption(id = "x_1")
),
reactive = TRUE
)
getAnywhereOption(id = "x_1")
getAnywhereOption(id = "x_2")
Note the status messages that I included for debugging:
DEBUG/push/before
[1] FALSE
DEBUG/lazy/before
Error in print(lazy) : argument is missing, with no default
DEBUG/is_lazy/before
[1] FALSE
DEBUG/lazy/after
[1] FALSE
For some reason, for this very calling stack structure, function reactr::setShinyReactive()
does not seem to recognize the default value for lazy
anymore while others (e.g. that of push
) seem to be recognized just fine.
To be more precise, without my workaround (see below), R would complain when reaching this code section. However, as you can see, the default value is defined and it also works just fine if the function is called stand-alone or from within nestr::setNested()
.
Workaround
When I change the argument name from lazy
to is_lazy
(or just include is_lazy
as well and then run lazy <- is_lazy
in the body), everything works just fine (see debug output above).
See DEBUG section in reactr::setShinyReactive()
Wildly guessing what's going on here
The first thing that comes to my mind is that this must have something to do with the lexical scoping mechanism as the behavior does not appear for "simple function call stacks".
The second guess is that maybe the S4 mechanism also causes some trouble here. Maybe also related to this issue?
Ok, I have to admit: that was a really stupid mistake. I unintentionally had a trailing
,
in the call tonestr::setNested()
insideoptionr::setAnywhereOption()
Here's a much simpler illustration:
Definitions
Apply
Solution
Removing the trailing
,
in the method definition ofsetAnywhereOption()
:Now it works just fine