>>>>> Pages, Herve >>>>> on Thu, 14 Nov 2019 19:13:47 +0000 writes:
> On 11/14/19 05:47, Hadley Wickham wrote: >> On Sun, Nov 10, 2019 at 2:37 AM Martin Maechler >> <maech...@stat.math.ethz.ch> wrote: >>> >>>>>>>> Gabriel Becker >>>>>>>> on Sat, 2 Nov 2019 12:37:08 -0700 writes: >>> >>> > I agree that we can be careful and narrow and still see a >>> > nice improvement in behavior. While Herve's point is valid >>> > and I understand his frustration, I think staying within >>> > the matrix vs c(matrix, array) space is the right scope >>> > for this work in terms of fiddling with inheritance. >>> >>> [.................] >>> >>> >>>>> Also, we seem to have a rule that inherits(x, c) iff c %in% class(x), >>>> >>>> good point, and that's why my usage of inherits(.,.) was not >>>> quite to the point. [OTOH, it was to the point, as indeed from >>>> the ?class / ?inherits docu, S3 method dispatch and inherits >>>> must be consistent ] >>>> >>>> > which would break -- unless we change class(x) to return the whole >>>> set of inherited classes, which I sense that we'd rather not do.... >>> >>> [................] >>> >>>> Note again that both "matrix" and "array" are special [see ?class] as >>>> being of __implicit class__ and I am considering that this >>>> implicit class behavior for these two should be slightly >>>> changed .... >>>> >>>> And indeed I think you are right on spot and this would mean >>>> that indeed the implicit class >>>> "matrix" should rather become c("matrix", "array"). >>> >>> I've made up my mind (and not been contradicted by my fellow R >>> corers) to try go there for R 4.0.0 next April. >> >> I can't seem to find the previous thread, so would you mind being a >> bit more explicit here? Do you mean adding "array" to the implicit >> class? > It's late in Europe ;-) > That's my understanding. I think the plan is to have class(matrix()) > return c("matrix", "array"). No class attributes added to matrix or > array objects. > It's all what is needed to have inherits(matrix(), "array") return TRUE > (instead of FALSE at the moment) and S3 dispatch pick up the foo.array > method when foo(matrix()) is called and there is no foo.matrix method. Thank you, Hervé! That's exactly the plan. >> Or adding it to the explicit class? Or adding it to inherits? >> i.e. which of the following results are you proposing to change? >> >> is_array <- function(x) UseMethod("is_array") >> is_array.array <- function(x) TRUE >> is_array.default <- function(x) FALSE >> >> x <- matrix() >> is_array(x) >> #> [1] FALSE >> x <- matrix() >> inherits(x, "array") >> #> [1] FALSE >> class(x) >> #> [1] "matrix" >> >> It would be nice to make sure this is consistent with the behaviour of >> integers, which have an implicit parent class of numeric: > I agree but I don't know if Martin wants to go that far for R 4.0. again, correct. In the mean time, thanks to Tomas Kalibera, my small change has been tested on all of CRAN and Bioc (Software) packages R CMD check <pkg> but no '--as-cran' nor any environment variable settings such as ((strongly recommended by me for package developers !)) _R_CHECK_LENGTH_1_CONDITION_=true _R_CHECK_LENGTH_1_LOGIC2_=verbose >From the package checks, and my own checks I've started noticing only today, that indeed, the _R_CHECK_LENGTH_1_CONDITION_=true environment variable setting --- stemming more or less directly from an R-devel (mailing list) proposal by Henrik Bengtsson -- and documented in help("if") since R 3.5.0, *together* with the proposal of class(<matrix>) |--> c("matrix", "array") is triggering many new ERRORs because the bad use of class(.) == "..." which I've blogged about is very often inside if(), i.e., if (class(object) == "foobar") # or ` != ` or Now in "new R-devel", and when object is a matrix, if ( class(object) == "foobar") <===> if (c("matrix","array") == "foobar") <===> if (c(FALSE, FALSE)) which is "fine" (i.e, just giving the infamous warning.. which is often surpressed by testthat or similar wrappers) unless you set the env.var .. as I think you R-devel readers all should do : > Sys.unsetenv("_R_CHECK_LENGTH_1_CONDITION_") > if(c(FALSE,FALSE)) 1 else 2 [1] 2 Warning message: In if (c(FALSE, FALSE)) 1 else 2 : the condition has length > 1 and only the first element will be used > Sys.setenv("_R_CHECK_LENGTH_1_CONDITION_" = TRUE) > if(c(FALSE,FALSE)) 1 else 2 Error in if (c(FALSE, FALSE)) 1 else 2 : the condition has length > 1 > > Hopefully that's the longer term plan though (maybe for R 4.1?). I'm not making promises here. Maybe if we could agree to make the equivalent of _R_CHECK_LENGTH_1_CONDITION_=true R 4.0.0's (unconditional?) default behavior, then at least the introduction of class(1L) |--> c("integer", "numeric") would be less problematic because most of the wrong uses of if(class(..) == "integer") would already have been eliminated ... Martin > Note that there are other situations that could follow e.g. > data.frame/list and probably more... > H. >> is_numeric <- function(x) UseMethod("is_numeric") >> is_numeric.numeric <- function(x) TRUE >> is_numeric.default <- function(x) FALSE >> >> x <- 1L >> is_numeric(x) >> #> [1] TRUE >> inherits(x, "numeric") >> #> [1] FALSE >> class(x) >> #> [1] "integer" >> >> Hadley >> > -- > Hervé Pagès > Program in Computational Biology > Division of Public Health Sciences > Fred Hutchinson Cancer Research Center > 1100 Fairview Ave. N, M1-B514 > P.O. Box 19024 > Seattle, WA 98109-1024 > E-mail: hpa...@fredhutch.org > Phone: (206) 667-5791 > Fax: (206) 667-1319 ______________________________________________ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel