tags:

views:

456

answers:

5

Say I have a bunch of functions, each with something likeMyFunction.1, etc. I want to pass these functions into another function, which prints out a small report. Ideally I'd like to be able to label sections of a report by which function is being used to generate the results.

So are there any nice ways of getting the name of a predefined function as a string?

+2  A: 

That may lead to parse(eval(...)) at which point you are open for this critique:

R> library(fortunes)
R> fortune("parse")

If the answer is parse() you should usually rethink the question.
   -- Thomas Lumley
      R-help (February 2005)

R>

So do your functions have to be called MyFunction.1 etc pp?

Dirk Eddelbuettel
Hah - I was afraid I'd get that fortune. I just wanted to be able to have a function I can call like compare.distribution.methods(c(two.choice, go.left, simple.random.sample), and get a table of results for each method in the vector. The nice-to-have would be not having to pass in a labels vector with the names I want, but that's certainly another option. I was just hoping for something that'd do it for me. If this is not part of the R flow, then all the better that this question is answered thus.
HamiltonUlmer
The S3 method dispatch does that for you! Don't fear the "OO", this would be a nice simple example to start using it. If only I had some kind and gentle docs to point you to ... Maybe Chambers "Software for Data Analysis" book from last year?
Dirk Eddelbuettel
+1  A: 

When a function is passed around as an object, it loses its name. See, for example, the results of the following lines:

str(lm)
lm

You can get the arguments and the body of the function, but not the name.

My suggestion would be to construct a named list of functions, where the name could be printed:

> somefns <- list(lm=lm, aggregate=aggregate)
> str(somefns)
List of 2
 $ lm       :function (formula, data, subset, weights, na.action, method = "qr", 
    model = TRUE, x = FALSE, y = FALSE, qr = TRUE, singular.ok = TRUE, 
    contrasts = NULL, offset, ...)  
 $ aggregate:function (x, ...) 

> somefns[[1]](dist ~ speed, data=cars)

Call:
somefns[[1]](formula = dist ~ speed, data = cars)

Coefficients:
(Intercept)        speed  
     -17.58         3.93  

> names(somefns)[[1]]
[1] "lm"
Harlan
+4  A: 

Another approach would be to pass the names of the functions into your report function, and then get the functions themselves with the get() command. For instance:

function.names <- c("which","all")
fun1 <- get(function.names[1])
fun2 <- get(function.names[2])

Then you have the names in your original character vector, and the functions have new names as you defined them. In this case, the all function is now being called as fun2:

> fun2(c(TRUE, FALSE))
[1] FALSE

Or, if you really want to keep the original function names, just assign them locally with the assign function:

assign(function.names[2], get(function.names[2]))

If you run this command right now, you will end up with the all function in your ".GlobalEnv". You can see this with ls().

Shane
+1  A: 

You can get the unevaluated arguments of a function via match.call. For example:

> x <- function(y) print(match.call()[2])
> x(lm)
lm()
Jonathan Chang
True, not but helpful here. If you say "z <- lm" and then x(z) you get "z", not "lm".
Harlan
True, although it's unclear what the right behavior is then. Which function is "canonical" and should be printed?
Jonathan Chang
In a functional language, the name of the function is not really important. You can easily rename functions, or have functions without names. The match.call function just gives you the name of the variable that held the function when it was being called, so in that sense, it's doing the only thing it can do. I don't know that "canonical" really comes into it...
Harlan
This is all true, but then what is the right answer in the context of the original question. I imagine Hamilton wants a function `foo` that generates reports of the form > foo(MyFunction.1, MyFunction.2) MyFunction.1 867 MyFunction.2 5309The question is if Hamilton sets `MyFunction.1 <- MyFunction.3`, should the report print out `MyFunction.1` or `MyFunction.3`?
Jonathan Chang
I should also mention that many functions, such as `lm`, use `match.call` to label its summary reports.
Jonathan Chang
MyFunction.1. Anything else requires telepathy on the part of the interpreter! The original name of the function is lost, per the S language definition, when you assign it to another variable. If you want the *original* name of the function, you have to store it in one of the several ways described above.
Harlan
So in light of this, what was your objection with my solution?
Jonathan Chang
A: 

what about this:

deparse(quote(foo.bar))
mariotomo