Open dereckmezquita opened 2 years ago
Note this error also occurs when trying to run code interactively. It seems that box
does not play nice with S4
.
Module:
#' @export
someClass <- methods::setClass(
"someClass",
slots = list(
example_slot = "character"
),
prototype = list(
example_slot = character()
)
)
#' @export
methods::setMethod("show", "someClass", \(object) {
cat("\n")
cat("Example slot:", object@example_slot, "\n")
cat("\n")
})
box::use(./utils/R/someModule)
Error in box::use(./utils/R/someModule) :
name '.cacheOnAssign' not found in 'env'
(inside “env$.cacheOnAssign”)
This error also occurs when creating new methods in S4
:
SomeMethod.R
methods::setGeneric("is.empty", \(x, ...) standardGeneric("is.empty"))
methods::setMethod("is.empty", "data.frame", \(x, ...) {
return(identical(dim(x), c(0, 0)))
})
box::use(./utils/R/someMethod)
Error in box::use(./utils/R/helpers) :
name '.cacheOnAssign' not found in 'env'
(inside “env$.cacheOnAssign”)
Calls: <Anonymous> ... tryCatchList -> tryCatchOne -> <Anonymous> -> rethrow -> throw
Execution halted
Unfortunately after a lot of testing it seems that the whole of the S4
system does not work with box
. This is greatly unfortunate since S4
is a great system and one of the standards in OOP
for R
.
Hi,
In the order from easiest to hardest:
First question, why am I getting this above error? It makes no sense, the
methods
package is part ofR
or it's included inbase
. I solved this by appendingmethods::
to my function calls:
That’s normal; first off, ‘methods’ isn’t included in ‘base’, and it isn’t by default loaded/attached in R except in interactive sessions. So this isn’t specific to ‘box’ (you’d have the same error in any script run non-interactively). But in addition, ‘box’ modules don’t attach any packages (except ‘base’), even in interactive sessions — see this FAQ.
Your fix works but the “preferred” solution is to use box::use()
instead of ::
:
box::use(methods)
#' @export
someClass <- methods$setClass(
…
But now I get this error; …
Error in box::use(./utils/R/someMinimalModule[someClass]) : name '.cacheOnAssign' not found in 'env'
This can be fixed by adding .cacheOnAssign <- FALSE
to your module source code. However, …
Unfortunately S4 does not, and (I believe) fundamentally cannot ever work with ‘box’. The reason for that is that S4 explicitly only supports defining classes and methods in packages or the R global environment, and nothing else. See also #95. In particular, S4 internally tries to load the code that defines an S4 class as a package (i.e. via require
), even if the code is actually a module. You can’t tell it not to do this, since that logic is hard-coded.
Maybe (!) it is possible to work around this limitation and cobble together some half-assed support for S4 in ‘box’ but unfortunately it isn’t even obvious whether that’s possible at all, and the documentation of S4 is notoriously poor, as noted in Advanced R:
S4 is a complex system and it can be challenging to use effectively in practice. This wouldn’t be such a problem if S4 documentation wasn’t scattered through R documentation, books, and websites. S4 needs a book length treatment, but that book does not (yet) exist.
Worse, what little S4 documentation exists is riddled with errors, both in the prose (which makes some sentences unintelligible) and in the actual example code!
My general recommendation (regardless of ‘box’!), echoing Advanced R, is to avoid S4 as much as possible. I’d go even further than Advanced R: don’t use S4 at all. Use S3 or R6, as appropriate, or build your own object system where neither of these works well. After all, R allows doing this, and it’s e.g. what ‘ggplot2’ did. S4 has many good ideas but its implementation is rather problematic.
Thank you very much for all that @klmr I really appreciate it.
It's very unfortunate as I really am a fan of S4
. I have experience with R6
and S3
as well so for now I think I will move over to those systems.
As I understood getting this really fixed would require making changes to how S4
works right?
Error description
My set up and minimal example
I have this set up:
someMinimalScript.R
someMinimalModule.R
Contents of
someMinimalScript.R
:This is importing a module who's contents are
someMinimalModule.R
:This is a set of tools which is designed to be used from the system command line (CLI tools). This is achieved by exporting the path to the tools in a
.bashrc
:We need to also do this in the project:
chmod 755 ./bin/*
.My errors
Once all of this is set up, I am getting this error when calling this tool from the command line:
First question, why am I getting this above error? It makes no sense, the
methods
package is part ofR
or it's included inbase
. I solved this by appendingmethods::
to my function calls:But now I get this error; I would appreciate any insight anyone could extend to get this resolved:
R version
‘box’ version
‘1.1.2’