[R] Question about substitute (and eval, parse and deparse)

Henrik Bengtsson hb at maths.lth.se
Wed Jan 23 18:50:12 CET 2002


I would like to define a function at run-time, but I just can't make it
work (please don't question why I want to do this, because that would be 
too much to explain). For example, I want to define the the following
function

  foo <- function(x) {
    cat("Function", "foo", "was called with argument", x, ".\n")
  }

However, I would like to create similar function where 'foo' is replaced 
with say 'bar' and 'x' is replaced with 'object'. I'll use the variables
'name' and 'arg' for this purpose;

  name <- "foo";
  arg <- "x";

Now I'll create the 'call' to be evaluate to define the new function:

  call <- substitute(fcn <- function(arg) { cat("Function", name, "was
   called with argument", arg, ".\n"); }, list=list(fcn=as.name(name),
   arg=as.name(arg), name=name))   

Now looking at the call things look a little bit strange:

  > print(call)
  foo <- function(arg) {
    cat("Function", "foo", "was called with argument", x, ".\n")
  }  

  > str(call)
  language foo <- function(arg) {     cat("Function", "foo", "was called
   with argument", x, ".\n") ...

Notice how the name ('foo') and the arguments to 'cat' ("foo", and 'x')
of the function are correct, but *not* the first argument/formal ('arg').
For me this is strange. Continuing anyway and evaluating this call by

  > eval(call)

will define the function 'foo'. Now looking at this function we get

  > print(foo)
  function(arg) { cat("Function", name, "was called with argument", arg,
   ".\n"); } 

where we see that 'name' and 'arg' now is back!? If we instead use 
body() we get the following

  > body(foo)
  {
      cat("Function", "foo", "was called with argument", x, ".\n")
  }  

which is what we expected and finally

  > attr(foo, "source")
  [1] "function(arg) { cat(\"Function\", name, \"was called with
   argument\", arg, \".\\n\"); }" 

which is not what we expected. Further more, calling 'foo' will *not*
work: 

  > foo(2)
  Error in cat("Function", "foo", "was called with argument", x, ".\n") :
          Object "x" not found 
  > foo(x=2)
  Error in foo(x = 2) : unused argument(s) (x ...) 
  > foo(arg=2)
  Error in cat("Function", "foo", "was called with argument", x, ".\n") :
          Object "x" not found 

I have also tried

  call <- substitute(fcn <- function(arg) { cat("Function", name,
   "was called with argument", argName, ".\n"); },
   list=list(fcn=as.name(name), arg=arg, name=name, argName=as.name(arg))) 

with the same result. So, it comes to the argument/formal 'arg'.


A STEP CLOSER?

If one first deparse the call and the parse into a new call, which is then
evaluated by 'eval': 

  > eval(parse(text=deparse(call)))

then it the body of the function gets correct but I still have problem
with the arguments/formals: 

  > print(foo)
  function(arg) {
    cat("Function", "foo", "was called with argument", x, ".\n") 
  }
  > body(foo)
  {
    cat("Function", "foo", "was called with argument", x, ".\n")
  }
  > attr(foo, "source")
  [1] "function(arg) {"
  [2] "    cat(\"Function\", \"foo\", \"was called with argument\", x,
   \".\\n\")" 
  [3] "}"

So, what is going on here? How should I do this in a correct way?

I really appreciate your help!

Henrik Bengtsson

Dept. of Mathematical Statistics @ Centre for Mathematical Sciences 
Lund Institute of Technology/Lund University, Sweden (+2h UTC)
Office: P316, +46 46 222 9611 (phone), +46 46 222 4623 (fax)
h b @ m a t h s . l t h . s e
http://www.maths.lth.se/matstat/staff/hb/



-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
r-help mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html
Send "info", "help", or "[un]subscribe"
(in the "body", not the subject !)  To: r-help-request at stat.math.ethz.ch
_._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._



More information about the R-help mailing list