代码之家  ›  专栏  ›  技术社区  ›  Aniko

在执行期间显示函数的实际参数列表

  •  4
  • Aniko  · 技术社区  · 14 年前

    我试图显示调用函数时提供的参数的实际值。` match.call'按照我想要的行执行某些操作,但它不计算变量。例如

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

    印刷品

    foo(x = 2)
    

    我对此很满意。然而:

    xxx <- 2
    foo(xxx)
    

    将打印

    foo(x = xxx)
    

    而不是 foo(x = 2) 就像我想要的那样。

    我尝试过各种组合 substitute , eval 和公司,但没有成功。

    2 回复  |  直到 10 年前
        1
  •  3
  •   kohske    14 年前

    我不知道这是不是最好的方法,但也许你可以通过:

    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)
    
        2
  •  7
  •   fabians    10 年前

    不久前,我编写了一个函数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])))
    }
    

    如果您需要保留关于调用的更多信息或使其格式更漂亮,例如:

    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)
    

    也许你可以用它来解决你的问题。