Verbatim command arguments: deparse(substitute(foo)) in a wrapper
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
精彩评论