开发者

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

开发者 https://www.devze.com 2023-02-04 11:03 出处:网络
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 t

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-interactiv开发者_JAVA百科ely 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.


Try this:

> "%PE%" <- function(x, ...) do.call(p.eval, list(substitute(x)))
> sum(1:3) %PE% 0
sum(1:3) -->  6 


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
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号