R has macros, though you'll have to install gtools to get it. defmacro and strmacro provide basic Lisp-inspired macros (note that I said "basic" - I know that a Common Lisper will chuckle at this sentence, but Common Lispers chuckle at the inferiority of all other languages, so it's not a big deal). The documentation for defmacro includes the reference to the original R News article by Thomas Lumley.
Every once in a while you get the urge to do some macro-related stuff because it makes your life much easier, as it is the only way to do something without requiring an extremely awkward function call.
First, consider the following function:
f <- function(x,y) {
z <- x+y
}
In the vast majority of cases, you would have no need to know which variable was passed as an argument in the function call. That's one reason for using a function, because you don't have to worry about a conflict with an existing variable name. But suppose you wanted to know the name of the variable that was passed in. How would you do that?
f <- function(x,y) {
print(deparse(substitute(x)))
print(deparse(substitute(y)))
}
> f(w1,w2)
[1] "w1"
[1] "w2"
[1] "w1"
[1] "w2"
[1] "xrz"
[1] "three333"
What if you want to know the name of arguments passed with ...? We can pull code directly from Lumley's R News article:
f <- function(...) {
print(substitute(list(...)))
}
> f(x,y,z)
list(x, y, z)
That doesn't give the names of the variables, but if you want that, you can make a simple modification to Lumley's code:
f <- function(...) {
print(as.character(substitute(list(...)))[-1])
}
> f(x,y,z)
[1] "x" "y" "z"
A situation in which I've done this is plotting. You have a function named regressPlot that takes a variable number of arguments: regressPlot <- function(...). You want to run a regression using the arguments you passed and then plot the results. You want to add a caption that uses the names of the variables in the regression. This can be done easily using code similar to that given above.
A second example of its use can be seen in the help for the attach function.
Finally, in this thread, it is pointed out that an alternative way to get the same result is
foo <- function(...) {
sapply(match.call()[-1], deparse)
}
0 comments:
Post a Comment