Henrik Bengtsson
2025-Oct-07 23:42 UTC
[Rd] Is structure(NA, class = c("def", "condition")) a valid 'condition' object?
I think structure(NA, class = c("def", "condition")) is a
valid
'condition' object. Am I wrong?
BACKGROUND:
The abstract 'condition' class: why type or mode can a
'condition' object have?
In help("condition"), we can read that:
"Conditions are objects inheriting from the abstract class condition.
..."
and then it specifies the API, i.e. the methods it should support, e.g.
"The functions conditionMessage and conditionCall are generic
functions that return the message and call of a condition."
Then we have several functions for creating 'condition' objects, e.g.
> simpleCondition
function (message, call = NULL)
{
class <- c("simpleCondition", "condition")
structure(list(message = as.character(message), call = call),
class = class)
}
AFAIK, all of them create 'condition' object of type 'list'.
CAN CONDITIONS BE ENVIRONMENTS OR ATOMIC OBJECTS?
However, is the list type a requirement? I cannot find it specified
anywhere. The way I interpret help("condition") and how it is
carefully written using terms like "abstract class" and not mentioning
the type anywhere, I take it as:
cnd1 <- structure(new.env(), class = c("abc",
"condition"))
and
cnd2 <- structure(NA, class = c("def", "condition"))
are both valid 'condition' objects, as long as we define the S3
methods for `conditionMessage()` and `conditionCall()`, e.g.
conditionMessage.abc <- function(c) "boom"
conditionCall.abc <- function(c) list()
conditionMessage.def <- function(c) "boom"
conditionCall.def <- function(c) list()
FWIW, I create 'condition' objects of type NA in my 'R.oo'
package
going back ~25 years.
Thanks,
Henrik
Duncan Murdoch
2025-Oct-08 12:32 UTC
[Rd] Is structure(NA, class = c("def", "condition")) a valid 'condition' object?
Besides `conditionMessage` and `conditionCall`, base R also has methods defined for `as.character` and `print`, but they appear to make no assumptions about the object other than having `conditionMessage` and `conditionCall` defined. The help page is silent about what type of thing `conditionCall()` should return, but the objects produced by the standard condition functions will return the `call` argument, which defaults to `NULL`, but could be a "call expression". So I'm not sure your definition of the `conditionCall()` methods is going to work: `list()` doesn't return an expression. Returning `NULL` would be better. Of course, in S3 "valid" isn't defined formally; it just means something that won't mess up. So it's quite possible `list()` is okay. Duncan Murdoch On 2025-10-07 7:42 p.m., Henrik Bengtsson wrote:> I think structure(NA, class = c("def", "condition")) is a valid > 'condition' object. Am I wrong? > > BACKGROUND: > > The abstract 'condition' class: why type or mode can a 'condition' object have? > > In help("condition"), we can read that: > > "Conditions are objects inheriting from the abstract class condition. ..." > > and then it specifies the API, i.e. the methods it should support, e.g. > > "The functions conditionMessage and conditionCall are generic > functions that return the message and call of a condition." > > Then we have several functions for creating 'condition' objects, e.g. > >> simpleCondition > function (message, call = NULL) > { > class <- c("simpleCondition", "condition") > structure(list(message = as.character(message), call = call), > class = class) > } > > AFAIK, all of them create 'condition' object of type 'list'. > > > CAN CONDITIONS BE ENVIRONMENTS OR ATOMIC OBJECTS? > > However, is the list type a requirement? I cannot find it specified > anywhere. The way I interpret help("condition") and how it is > carefully written using terms like "abstract class" and not mentioning > the type anywhere, I take it as: > > cnd1 <- structure(new.env(), class = c("abc", "condition")) > > and > > cnd2 <- structure(NA, class = c("def", "condition")) > > are both valid 'condition' objects, as long as we define the S3 > methods for `conditionMessage()` and `conditionCall()`, e.g. > > conditionMessage.abc <- function(c) "boom" > conditionCall.abc <- function(c) list() > > conditionMessage.def <- function(c) "boom" > conditionCall.def <- function(c) list() > > FWIW, I create 'condition' objects of type NA in my 'R.oo' package > going back ~25 years. > > Thanks, > > Henrik > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel
Ivan Krylov
2025-Oct-26 14:31 UTC
[Rd] Is structure(NA, class = c("def", "condition")) a valid 'condition' object?
On Tue, 7 Oct 2025 16:42:12 -0700 Henrik Bengtsson <henrik.bengtsson at gmail.com> wrote:> I think structure(NA, class = c("def", "condition")) is a valid > 'condition' object. Am I wrong?For what it's worth, there are a few places in base R where error and warning conditions are assumed to contain $call and $message elements: cnd2 <- structure(NA, class = c("cnd2", "error", "condition")) conditionMessage.cnd2 <- \(...) "my message" conditionCall.cnd2 <- \(...) NULL # These work well: cnd2 # <cnd2: my message> stop(cnd2) # Error: my message # These fail: tools::assertError(stop(cnd2), 'cnd2', verbose=TRUE) # Error in error[[1L]]$message : $ operator is invalid for atomic # vectors tools::assertWarning( warning( structure(cnd2, class = c('cnd2', 'warning', 'condition')) ), 'cnd2', verbose=TRUE ) # Error in warning[[1L]]$message : $ operator is invalid for atomic # vectors (\(x = stop(cnd2)) ls.str())() # x : Error in o$message : $ operator is invalid for atomic vectors A few more similar code paths can be found in 'methods', 'compiler', and R CMD check using static analysis (and a lot of false positives in 'stats' model objects), but I'm not sure whether it's possible to reach them with a custom error condition. Is this worth preparing a patch for? -- Best regards, Ivan