From hb at biostat.ucsf.edu  Mon Sep 30 06:02:24 2013
From: hb at biostat.ucsf.edu (Henrik Bengtsson)
Date: Sun, 29 Sep 2013 21:02:24 -0700
Subject: [Rd] how to interpose my own "[" function?
In-Reply-To: <20130930032629.GA52400@piskorski.com>
References: <20130930032629.GA52400@piskorski.com>
Message-ID: <CAFDcVCQ3-Tn6nO-ckqpPK5zGq3QddrR_2m++xG4s7wm7D4Nsng@mail.gmail.com>

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



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