2010-08-13 22 views
4

我試圖顯示函數調用時提供的參數的實際值。 `match.call'按照我想要的方式做了一些事情,但它並不評估變量。例如在執行過程中顯示函數的實際參數列表

foo <- function(x) match.call() 
foo(2) 

打印

foo(x = 2) 

,我很高興。但是:

xxx <- 2 
foo(xxx) 

將打印

foo(x = xxx) 

,而不是foo(x = 2)因爲我想擁有它。

我嘗試過substitute,eval和公司的各種組合,但沒有成功。

回答

3

我不知道這是不是最好的辦法,但可能你可以做到這一點:

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) 
+0

哦,棘手!它解決了直接在'match.call()'上使用'eval'會再次調用該函數的問題。謝謝! – Aniko 2010-08-14 15:28:48

7

我寫了一個函數expand.call(),你想要做什麼(我想.. 。) 不久以前。事實上,它確實多了幾分:

#' 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]))) 
} 

你通常會以此爲match.call()如果你需要保留一些一些更多的信息關於呼叫或將其格式化更漂亮,像一個替代品:

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) 

也許你可以用它來解決你的問題。

+1

這是一個很棒的功能!不過,我認爲'eval'這個形式化的參數缺失了。如果我可能會添加一個建議:也許你會考慮命名該參數'doEval',以免引起與函數'eval'的混淆。 – BenBarnes 2013-03-27 07:57:31

+0

謝謝,@BenBarnes。我做了你所建議的改變。 – fabians 2013-04-19 11:38:17

+0

使用適用於搜索路徑的評估錯誤。如果你定義了一個變量c,那麼它將被評估爲c原始函數。更好地使用for循環。 – ThomasP85 2014-11-14 08:16:46

相關問題