I am trying to display the actual values of the parameters that were supplied when the function was called. `match.call' does something along the lines I want but it does not evaluate variables. For example
foo <- function(x) match.call()
foo(2)
prints
foo(x = 2)
and I am happy with that. However:
xxx <- 2
foo(xxx)
will print
foo(x = xxx)
instead of foo(x = 2)
as I would like to have it.
I have tried various combinations of substitute
, eval
, and company, but was not succesful.
I wrote a function expand.call() that does what you want (I think...) a while ago. Actually, it does a little more:
#' Return a call in which all of the arguments which were supplied
#' or have presets are specified by their full names and supplied
#' or default values.
#'
#' @param definition a function. See \code{\link[base]{match.call}}.
#' @param call an unevaluated call to the function specified by definition.
#' See \code{\link[base]{match.call}}.
#' @param expand.dots logical. Should arguments matching ... in the call be
#' included or left as a ... argument? See \code{\link[base]{match.call}}.
#' @param doEval logical, defaults to TRUE. Should function arguments be
#' evaluated in the returned call or not?
#'
#' @return An object of class call.
#' @author fabians
#' @seealso \code{\link[base]{match.call}}
expand.call <- function(definition=NULL,
call=sys.call(sys.parent(1)),
expand.dots = TRUE,
doEval=TRUE)
{
safeDeparse <- function(expr){
#rm line breaks, whitespace
ret <- paste(deparse(expr), collapse="")
return(gsub("[[:space:]][[:space:]]+", " ", ret))
}
call <- .Internal(match.call(definition, call, expand.dots))
#supplied args:
ans <- as.list(call)
if(doEval & length(ans) > 1) {
for(i in 2:length(ans)) ans[[i]] <- eval(ans[[i]])
}
#possible args:
frmls <- formals(safeDeparse(ans[[1]]))
#remove formal args with no presets:
frmls <- frmls[!sapply(frmls, is.symbol)]
add <- which(!(names(frmls) %in% names(ans)))
return(as.call(c(ans, frmls[add])))
}
You would normally use this as a substitute for match.call() if you need to preserve some some more info about the call or have it formatted more nicely, like:
foo <- function(x, bar="bar", gnurp=10, ...) {
call <- expand.call(...)
return(call)
}
> foo(2)
foo(x = 2, bar = "bar", gnurp = 10)
> xxx <- 2
> foo(xxx)
foo(x = 2, bar = "bar", gnurp = 10)
> foo(xxx, b="bbbb")
foo(x = 2, bar = "bbbb", gnurp = 10)
> foo(xxx, b="bbbb", doEval=FALSE)
foo(x = xxx, bar = "bbbb", doEval = FALSE, gnurp = 10)
Maybe you can use it to solve your problem.
I don't know if this is the best way, but probably you can do it by:
x<-"a"
y<-mean
z<-1
foo <- function(x,y,z) {
do.call("call",
c(list(as.character(match.call()[[1]])),
lapply(as.list(match.call())[-1],eval)))
}
foo(x,y,z)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With