Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Verbatim command arguments: deparse(substitute(foo)) in a wrapper

Tags:

r

Here's a little puzzler for those fluent in the nitty-gritty of how the R evaluator handles function calls. Suppose I wanted to write a function that takes an R statement, same as what I'd write at the command line, and echoes both it, and the evaluated result. Example:

 > p.eval(sum(1:3))
 sum(1:3) --> 6

That's easy; here's the definition of p.eval():

p.eval <- function(v,prefix="--> ") { 
   cmd <- deparse(substitute(v)); cat(cmd,prefix,v,"\n") 
}

But suppose I now want to write a wrapper around p.eval, to be invoked the same way; perhaps as a somewhat demented binary operator with a dummy second argument:

%PE% <- function(x,...) p.eval(x)

I'd like to invoke it like so: sum(1:3) %PE% 0 should be equivalent to the old p.eval(sum(1:3)). This doesn't work, of course, because the deparse(substitute()) of p.eval() now gives x.

Question to the enlightened: is there a way to make this work as I desire?.. For this particular usage, I'm quite fine with defining %PE% by copying/pasting the one-liner definition of p.eval, so this question is mostly academic in nature. Maybe I'll learn something about the nitty-gritty of the R evaluator :)

P.S.: Why might one find the above functions useful?.. Suppose I develop some analysis code and invoke it non-interactively through org-babel (which is most definitely worth playing with if you are an Org-mode and/or an Emacs user). By default, org-babel slurps up the output as things are evaluated in the interpreter. Thus, if I want to get anything but raw numbers, I have to explicitly construct strings to be printed through cat or paste, but who wants to do that when they are flying through the analysis?.. The hack above allows you to simply append %PE%0 after a line that you want printed, and this echoes the command to the org output.

like image 272
Leo Alekseyev Avatar asked Jan 12 '11 01:01

Leo Alekseyev


2 Answers

Try this:

> "%PE%" <- function(x, ...) do.call(p.eval, list(substitute(x)))
> sum(1:3) %PE% 0
sum(1:3) -->  6 
like image 79
G. Grothendieck Avatar answered Oct 29 '22 14:10

G. Grothendieck


Also could just have p.eval return "v" and then:

 p.eval <- function(v,prefix="--> ") {
        cmd <- deparse(substitute(v)); cat(cmd,prefix,v,"\n") ; return(v)  } 
"%PE%" <- function(x, y=NULL) x 
 sum(1:3) %PE% Inf
 #[1] 6  
sum(1:3) %PE%   # won't accept single argument
  r   # give it anything
 #[1] 6
like image 44
IRTFM Avatar answered Oct 29 '22 14:10

IRTFM