[Rd] c(<Matrix>, <Matrix>) / help(dotsMethods) etc

Martin Maechler maechler at stat.math.ethz.ch
Sat Sep 10 17:27:24 CEST 2016


I have been asked  (by Roger; thank you for the good question,
       	    	    and I hope it's fine to answer to the public) :
       
    > with Pi a sparse matrix and x,y, and ones
    > compatible n-vectors — when I do:

    >> c(t(x) %*% Pi %*% ones, t(ones) %*% Pi %*% y )
    > [[1]] 1 x 1 Matrix of class "dgeMatrix"
    > [,1] [1,]
    > 0.1338527
    > [[2]] 1 x 1 Matrix of class "dgeMatrix"
     [,1] [1,]
    > 0.7810341

    > I get a list whereas if Pi is an ordinary matrix I get a
    > vector.  Is this intentional?

Well, no.  But it has been "unavoidable" in the sense that it had not
been possible to provide S4 methods for '...' in the "remote"
past, when  Matrix was created.

Later ... also quite a few years ago, John Chambers had added
that possibility, with still some limitation (all '...' must be
of the same class), and also plans to remove some of the
limitations, see   ?dotsMethods  in R.

I honestly have forgotten the history of my trying to provide 'c'
methods for our "Matrix" objects after the  'dotsMethods'
possibility had emerged,  but I know I tried and had not seen a
way to succeed "satisfactorily",
but maybe I now think I maybe should try again.
I currently think this needs changes to R before it can be done
satisfactorily, and this is the main reason why this is a public
answer to R-devel at ..., but I'm happy if I'am wrong.

The real challenge here is that I think that if it  should "work",
it should work so in all cases, e.g., also for

    c(NA, 3:2, Matrix(2:1), matrix(10:11))

and that's not so easy, e.g., the following class and method
definitions do *not* achieve the desired result:

## "mMatrix" is already hidden in Matrix pkg:
setClassUnion("mMatrix", members = c("matrix", "Matrix"))
setClassUnion("numMatrixLike", members =
                c("logical", "integer","numeric", "mMatrix"))

c.Matrix <- function(...) unlist(lapply(list(...), as.vector))
## NB: Must use   signature  '(x, ..., recursive = FALSE)' :
setMethod("c", "Matrix", function(x, ..., recursive) c.Matrix(x,
...))
## The above is not sufficient for
##    c(NA, 3:2, <Matrix>, <matrix>) :
setMethod("c", "numMatrixLike", function(x, ..., recursive)
   c.Matrix(x, ...))

## but the above does not really help:

> c(Diagonal(3), NA, Matrix(10:11))   ## works fine,
 [1]  1  0  0  0  1  0  0  0  1 NA 10 11

> c(NA, Diagonal(3)) ## R's lowlevel c() already decided to use list():
[[1]]
 [1] NA

[[2]]
     [,1] [,2] [,3]
     [1,]    1    .    .
     [2,]    .    1    .
     [3,]    .    .    1

>
----------------------------------------------

BTW, I (and the package users) suffer from exactly the same
problem with the "MPFR" (multi precision numbers) provided by my
package Rmpfr:

> require(Rmpfr)
> c(mpfr(3,100), 1/mpfr(7, 80)) ## works fine
2 'mpfr' numbers of precision  80 .. 100  bits
[1]                            3 0.14285714285714285714285708

> c(pi, 1/mpfr(7, 80)) ## "fails" even worse than in 'Matrix' case
[[1]]
[1] 3.141593

[[2]]
'mpfr1' 0.14285714285714285714285708

> 


Yes, it would be very nice  if  c(.)  could be used to
concatenate quite arbitrary  R objects into one long atomic
vector, but I don't see how to achieve this easily.

The fact, that  c()  just builds a list of its arguments if it
("thinks" it) cannot dispatch to a method, is a good strategy,
but I'd hope it should be possible to have c() try to do better
(and hence work for this case, and
without a noticable performance penalty.

Suggestions are very welcome.
Martin



More information about the R-devel mailing list