From atp at piskorski.com  Mon Sep 30 05:26:29 2013
From: atp at piskorski.com (Andrew Piskorski)
Date: Sun, 29 Sep 2013 23:26:29 -0400
Subject: [Rd] how to interpose my own "[" function?
Message-ID: <20130930032629.GA52400@piskorski.com>

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>



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