[Rd] how to interpose my own "[" function?

Henrik Bengtsson hb at biostat.ucsf.edu
Mon Sep 30 06:02:24 CEST 2013


Typically you use NextMethod(), but otherwise you can either "unclass"
your object first or use .subset().  Not sure from ?.subset whether
that is ok to use or not.

/Henrik

On Sun, Sep 29, 2013 at 8:26 PM, Andrew Piskorski <atp at piskorski.com> wrote:
> I want to create my own "[" function (for use on vectors, matrices,
> arrays, etc.), which calls the stock R "[", does some additional work,
> and then finally returns the modified result.
>
> But, how do I properly call the stock R "[" function?  It takes a
> varying number of positional arguments, and its R-level closure is
> just:  .Primitive("[")  It's implemented by do_subset_dflt in
> src/main/subset.c.
>
> The only thing I've come up with so far is using eval after crudely
> re-constructing the original incoming call (example below), which is
> both very slow and gets some of the semantics wrong.
>
> Is there some good way for my function to just say, "take ALL my
> incoming arguments, whatever they might be, and pass them as-is to
> .Primitive('['), then return control to me here"?  Or said another
> way, what I want is to hook the end of the R-level "[" function and do
> some extra work there before returning to the user.
>
> Basically, where should I look to figure out how to do this?  Is it
> even feasible at all when the call I want to intercept is implemented
> in C and is Primitive like "[" is?  Is there some other technique I
> should be using instead to accomplish this sort of thing?
>
> Thanks for your help!  Example of awful eval-based code follows:
>
>
> my.subset <- function(x ,i ,j ,... ,drop=TRUE) {
>    brace.fcn <- get("[",pos="package:base")
>    code <- 'brace.fcn(x,'
>    if (!missing(i))    code <- paste(code ,'i' ,sep="")
>    # This fails to distinguish between the mat[1:21] and mat[1:21,] cases:
>    if (length(dim(x)) > 1 && (missing(i) || length(dim(i)) <= 1))
>       code <- paste(code ,',' ,sep="")
>    if (!missing(j))    code <- paste(code ,'j' ,sep="")
>    if (!missing(...))  code <- paste(code ,',...' ,sep="")
>    if (!missing(drop)) code <- paste(code ,',drop=drop' ,sep="")
>    code <- paste(code ,')' ,sep="")
>    result <- eval(parse(text=code))
>    # FINALLY we have the stock result, now modify it some more...
>    result
> }
>
> --
> Andrew Piskorski <atp at piskorski.com>
>
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel



More information about the R-devel mailing list