How do I partially bind/apply arguments to a function in R?
This is how far I got, then I realized that this approach doesn't work...
bind <- function(fun,...)
{
argNames <- names(formals(fun))
bindedArgs <- list(...)
bindedNames <- names(bindedArgs)
function(argNames[!argNames %in% bindedArgs])
{
#TODO
}
}
Thanks!
Here's a version of Curry that both preserves lazy evaluation of function argument, but constructs a function that prints moderately nicely:
Curry <- function(FUN, ...) {
args <- match.call(expand.dots = FALSE)$...
args$... <- as.name("...")
env <- new.env(parent = parent.frame())
if (is.name(FUN)) {
fname <- FUN
} else if (is.character(FUN)) {
fname <- as.name(FUN)
} else if (is.function(FUN)){
fname <- as.name("FUN")
env$FUN <- FUN
} else {
stop("FUN not function or name of function")
}
curry_call <- as.call(c(list(fname), args))
f <- eval(call("function", as.pairlist(alist(... = )), curry_call))
environment(f) <- env
f
}
It basically works by generating an anonymous function in exactly the same way you would if you were constructing the partial binding yourself.
Actually, this seems to work as a work around
bind <- function(fun,...)
{
boundArgs <- list(...)
formals(fun)[names(boundArgs)] <- boundArgs
fun
}
However, ideally I want the bound arguments to disappear completely from the new function so that calls to the new function can happen with name specification, e.g. with add <- function(a,b) a+b I would like (bind(add,a=2))(1) to return 3.
Have you tried looking at roxygen's Curry function?
> library(roxygen)
> Curry
function (FUN, ...)
{
.orig = list(...)
function(...) do.call(FUN, c(.orig, list(...)))
}
<environment: namespace:roxygen>
Example usage:
> aplusb <- function(a,b) {
+ a + 2*b
+ }
> oneplusb <- Curry(aplusb,1)
> oneplusb(2)
[1] 5
Edit:
Curry is concisely defined to accept named or unnamed arguments, but partial application of fun to arguments by way of formal() assignment requires more sophisticated matching to emulate the same functionality. For instance:
> bind <- function(fun,...)
+ {
+ argNames <- names(formals(fun))
+ boundArgs <- list(...)
+ boundNames <- names(boundArgs)
+ if(is.null(boundNames)) {
+ formals(fun)[1:length(boundArgs)] <- boundArgs
+ } else {
+ formals(fun)[match(names(boundArgs),argNames)] <- boundArgs
+ }
+ fun
+ }
> oneplusb <- bind(aplusb,1)
> oneplusb(2)
Error in 2 * b : 'b' is missing
Because the first argument in this function is still a, you need to specify which argument 2 is intended for (b=), or pass it as the second argument.
> oneplusb
function (a = 1, b)
{
a + 2 * b
}
> oneplusb(b=2) ## or oneplusb(,2)
[1] 5
Related
I want to make a special behavour for function when an argument b is NA. I don't want to do this with if so I prefer generic. This is my try:
foo <- function(x) {
UseMethod("foo", x)
}
foo.numeric <- function(x) {
print("numeric")
}
foo.default <- function(x) {
print("def")
}
foo.NA <- function(x) {
print("na")
}
now when I run foo(NA) i want to run foo.NA() but foo.default() is executed.
If I want to see what expression was passed into a function, I can retrieve it using substitute.
f <- function(x)
{
substitute(x)
}
f(sin(pi))
## sin(pi)
(f returns an object of class call. substitute is usually combined with deparse to turn it into a character vector, but I don't care about that here.)
I want to repeat this with arguments in .... This attempt only returns the first argument:
g <- function(...)
{
substitute(...)
}
g(sin(pi), cos(pi / 2))
## sin(pi)
This attempt throws an error:
h <- function(...)
{
lapply(..., subsitute)
}
h(sin(pi), cos(pi / 2))
## Error in match.fun(FUN) :
## 'cos(pi/2)' is not a function, character or symbol
This attempt throws a different error:
i <- function(...)
{
lapply(list(...), substitute)
}
i(sin(pi), cos(pi / 2))
## Error in lapply(list(...), substitute) :
## '...' used in an incorrect context
How do I retrieve the expressions that I passed into ...?
if you want to keep objetcts of class call:
i <- function(...)
{
l <- match.call()
l <- as.list(l)
l <- l[-1]
l
}
i <- function(...)
{
l <- match.call()
l[[1]] <- as.name("expression")
l
}
i(sin(pi), cos(pi/2))
Or maybe you just need the match.call depending what you want to do after.
hth
Try this one:
substitute_multi <- function(...) {
f <- function(e1, ...) {
if (missing(e1)) return(NULL)
else return(list(substitute(e1), substitute_multi(...)))
}
unlist(f(...))
}
Which gives for example:
substitute_multi(x, g(y), 1+2+3)
## [[1]]
## x
##
## [[2]]
## g(y)
##
## [[3]]
## 1 + 2 + 3
You may also call as.expression on the result to get an expression object.
IMHO, this solution is not as elegant as the other one, but gives some insight on how ... deals with function arguments. :)
I am trying to write a function which would take as argument a function call, evaluates numeric args of this function call and then return corresponding character vector. This is what I have came up with:
ConvertToCharacter <- function(function.call) {
call.str <- deparse(substitute(function.call))
return(call.str)
}
> a <- 1
> ConvertToCharacter(sum(2, a))
"sum(2, a)"
> ConvertToCharacter(ddply(mtcars, .(vs), summarize, col=mean(cyl)))
"ddply(mtcars, .(vs), summarize, col = mean(cyl))"
Now, I want the numeric args to be evaluated before getting converted into a character vector. So that ConvertToCharacter(sum(2, a)) would return "sum(2, 1)" instead. I tried passing env=parent.frame() to subsitute but it won't work. Any idea how I could go with this?
Thanks!
You need to recursively inspect your call, evaluate the symbols, and sub in the values for the numeric ones like so:
ConvertToCharacter <- function(function.call, env=parent.frame()) {
call <- substitute(function.call)
convert_recurse <- function(x, env) {
if(is.call(x)) {
return(as.call(lapply(x, match.fun(sys.call()[[1]]), env=env)))
} else if (
is.symbol(x) &&
is.numeric(try(val <- eval(x, env), silent=TRUE))
) {
return(val)
} else {
return(x)
}
}
deparse(convert_recurse(call, env))
}
a <- 1
ConvertToCharacter(sum(2, a))
lbsToKgs <- 2.2
ConvertToCharacter(ddply(mtcars, .(vs), summarize, col=mean(cyl), wtkg=mean(wt * lbsToKgs)))
And this is what you get:
# [1] "sum(2, 1)"
# [1] "ddply(mtcars, .(vs), summarize, col = mean(cyl), wtkg = mean(wt * "
# [2] " 2.2))"
Also, credit to Robert for the workaround the apply/Recall issue.
ConvertToCharacter <- function(function.call) {
library(stringr)
str_replace(deparse(substitute(function.call)),"a",eval(a,envir=.GlobalEnv))
}
I hope it helps
I have a very simple piece of code that produces:
afun <- function(a) {
return(bfun(...))
}
bfun <- function(...) {
return(a + 1)
}
> afun(1)
Error in afun(1) : '...' used in an incorrect context
But what R doesn't like here?
In your function afun:
afun <- function(a) {
return(bfun(...))
}
the ... is simply an argument (with no default value), just like any other. It doesn't mean "automatically suck up all arguments passed to the parent function". It just as if you had defined bfun as:
bfun <- function(b) {
return(b + 1)
}
and then tried to do:
afun <- function(a) {
return(bfun(b))
}
In order for a to be passed on to bfun, you either have to gather that argument yourself using something like match.call, or you have to hard code it (e.g. return(bfun(a))), or you have to use ... as an argument (and the only argument) to afun.
Typically, ... is used for passing additional arguments on to a subsequent function.
If you want afun to return function with variable number of the arguments just return bfun as a return value of afun. In R these are called closures
This is what you get:
afun <- function(a) {
print(a)
function (b, ...){
print(paste(b, ..., sep = " "))
}
}
The result is:
bfun <- afun("in afun body") # "in afun body from print(a)
bfun("arg1") # "arg1" from print(paste(b, ..., sep = " "))
bfun("arg1", "arg2", "arg3") # "arg1 arg2 arg3" from print(paste(b, ..., sep = " "))
What type of object is passed to myFunc as x? It doesn't seem to be an expression, nor a function and str just evaluates it. I understand that I can use force() to evaluate. I'm wondering if there's some way to gather more information about x without evaluating it.
myFunc = function( x )
{
is.expression( x )
is.function( x )
str( x )
}
myFunc( { x = 5; print( x + 1 ) } )
You can use match.call for extracting the arguments:
myFunc <- function( x ) {
x <- match.call()$x
print(class(x))
print(typeof(x))
print(mode(x))
print(storage.mode(x))
print(is.expression(x))
print(is.call(x))
if (is.call(x)) print(x[[1]])
}
myFunc({x = 5; print("a")})
myFunc(expression(x))
x <- factor(1)
myFunc(x)
myFunc(1)
Probably I need to say that { is a function in R, so {...} is no more than call.
Updated: why x is not function while { is function:
f <- function(x) {
x <- match.call()$x
print(eval(x[[1]]))
print(is.function(eval(x[[1]])))
}
f({1})
I think class would do the trick... See docs.
EDIT: According to the docs,
for {, the result of the last expression evaluated
Which means the class is the class resulting from the evaluation, which is why it not showing up as an "expression". It is being passed after evaluation.
Dason just posted a similar response to this on Talkstats.com for determining if an object is a data frame or a list (click here for a link to that post). I just extended it to an expression which I think suits your needs.
j.list <- function(list, by = NULL){
print("list")
print(list)
}
j.data.frame <- function(df, ..., by = NULL){
print("data frame")
print(df)
}
j.expression <- function(expression, by = NULL){
print("expression")
print(expression)
}
j <- function(x, ...){
UseMethod("j")
}
j(list(test = "this is a list"))
j(data.frame(test = 1:10))
j(expression(1+ 0:9))