Re: [Rd] creating a '[' method for an S4 class

From: Martin Maechler <maechler_at_stat.math.ethz.ch>
Date: Sat, 07 Jul 2012 10:20:27 +0200

>>>>> Benilton Carvalho <beniltoncarvalho_at_gmail.com> >>>>> on Sat, 7 Jul 2012 03:49:34 +0100 writes:

> Hi,

> I'm working on an S4 class that is expected to behave like an array.

> I have some difficulties when defining '[' and I wonder if someone
> could point me to the right direction:

> 1) Call the S4 object "obj"
> 2) Assume dim(obj) = c(10, 4, 2)
> 3) Suppose someone calls: obj[1:3,] , which is a mistake, given
> dim(obj); how do I detect such situations?

yes, a good question with a tricky answer. Actually not only relevant for S4, and hence one of the basic tricks is already visible in [.data.frame : --- you need to use nargs() in addition to others more well known tools ---

*and* it is trickier than you think:

Not only want you differentiate between   obj[ i , ]
and
  obj[ i , , ]

but more importantly,
between
  obj[ i ]
and
  obj[ i , ]
and that's where nargs() comes into play (as 'j', the 2nd argument is missing in both cases, you cannot  use that check alone).

In my CRAN package Rmpfr {Interface R <--> MPFR library for

                                                      arbitrary precision arithmetic} I use S4 classes and methods extensively, as two argument dispatch is the most natural paradigm for arithmetic. Here is the part (from Rmpfr/R/array.R ) which implements "[" for 'mpfrArray':
{but you probably want the full package in src to understand all  the details}:

.mpfrA.subset <- function(x,i,j, ..., drop) {

    nA <- nargs()
    if(getOption("verbose"))

        message(sprintf("nargs() == %d mpfrArray indexing ... ", nA))

    r <- getD(x)# data part of x, a list()     if(nA == 2) ## A[i]

        return(new("mpfr", r[i]))
    ## else: nA != 2 : nA > 2 -
    dim(r) <- (dx <- dim(x))
    dimnames(r) <- dimnames(x)
    r <- r[i,j, ..., drop=drop]
    if(drop && is.null(dim(r)))

        new("mpfr", r)
    else {

        D <- if(is.null(dr <- dim(r))) # ==> drop is FALSE; can this happen?
            rep.int(1L, length(r)) else dr
        x_at_Dim <- D
        x_at_Dimnames <- if(is.null(dn <- dimnames(r)))
            vector("list", length(D)) else dn
	if(length(D) == 2 && class(x) != "mpfrMatrix")
	    ## low-level "coercion" from mpfrArray to *Matrix :
	    attr(x,"class") <- getClass("mpfrMatrix")@className
        attributes(r) <- NULL
        setDataPart(x, r, check=FALSE)

    }
}

## "["
setMethod("[", signature(x = "mpfrArray", i = "ANY", j = "ANY", drop = "ANY"),

          .mpfrA.subset)

## this signature needs a method here, or it triggers the one for "mpfr" setMethod("[", signature(x = "mpfrArray", i = "ANY", j = "missing",

                         drop = "missing"),
          .mpfrA.subset)




> Thank you very much for your attention and time,
> benilton



R-devel_at_r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel Received on Sat 07 Jul 2012 - 08:24:12 GMT

This quarter's messages: by month, or sorted: [ by date ] [ by thread ] [ by subject ] [ by author ]

All messages

Archive maintained by Robert King, hosted by the discipline of statistics at the University of Newcastle, Australia.
Archive generated by hypermail 2.2.0, at Mon 09 Jul 2012 - 08:10:31 GMT.

Mailing list information is available at https://stat.ethz.ch/mailman/listinfo/r-devel. Please read the posting guide before posting to the list.

list of date sections of archive