使用match.call将所有参数传递给其他函数

时间:2015-03-29 09:11:08

标签: r arguments parameter-passing

来自?match.call

  

match.call最常用于两种情况:   [...]将大部分呼叫传递给另一个功能[...]

在阅读之后,我希望我可以使用match.call当我想将一个函数的所有参数传递给另一个函数而不逐一列出这些参数时。

示例:outer1逐个传递参数,outer2使用match.call

outer1 <- function(a, b, c) {
  inner1(a, b, c)
}

inner1 <- function(a, b, c) { 
  return(a + b + c$first + c$second)
}

outer2 <- function(a, b, c) {
   mycall <- match.call()
   inner2(mycall)
}

inner2 <- function(call) {
   return(call$a + call$b + call$c$first + call$c$second)
}

outer1(1, 2, list(first = 3, second = 4)) # OK: 10
outer2(1, 2, list(first = 3, second = 4)) # OK: 10

-1而不是1传递给outer2时,会出现第一个问题:

outer2(-1, 2, list(first = 3, second = 4)) # Error in call$a + call$b : non-numeric argument to binary operator

问题1 :传递-1而不是1之间的技术差异是什么?我知道

typeof(quote(1)) # double
typeof(quote(-1)) # language

但我想我在第二种情况下传递language对象的事实不是(唯一的)相关差异,因为将类型语言传递给参数c有效({{1} })。

为了克服上述问题,我尝试typeof(quote(list(first = 3, second = 4))) # language eval类型的所有参数:

language

问题2: outer3 <- function(a, b, c) { parsedCall <- lapply(match.call()[-1L], FUN=function(argument) { if(is.language(argument)) { return(eval(argument)) } else { return(argument) } }) inner3(parsedCall) } inner3 <- function(parsedCall) { return(parsedCall$a + parsedCall$b + parsedCall$c$first + parsedCall$c$second) } outer3(-1, 2, list(first = 3, second = 4)) # OK: 8 中的方法似乎&#34;工作&#34;但我还需要考虑进一步的陷阱吗? (我知道在某些情况下评估参数可能是不利的,但对于我的情况,这应该不是问题。)

问题3:我认为将所有参数传递给另一个函数的愿望并不常见。是否有比我更好/标准的方法?

问题4:将原始outer3传递给内部函数并执行call内容是否有利?如果我想将参数作为eval函数中的局部变量(而不是inner列表的元素),这会有用吗?然后,parsedCall的正文可能与inner3的正文相同(在使用当前解决方案时,我必须将inner1替换为a+b)。

1 个答案:

答案 0 :(得分:1)

关于你的问题:

  

我认为将所有参数传递给另一个函数的愿望是   并非罕见。是否有比我更好/标准的方法   做?

然后我会说这是传递参数的更常见方式:

> inner1 <- function(a, b, c) { 
+   return(a + b + c$first + c$second)
+ }
> 
> outer3 <- function(a, b, c) {
+   mycall <- match.call()
+   mycall[[1]] <- as.symbol("inner1") # use inner 1
+   eval(mycall)
+ }
> 
> outer4 <- function(a, b, c) {
+   .args <- as.list(match.call()[-1]) # use inner 1
+   do.call(inner1, .args)
+ }
> 
> outer3(-1, 2, list(first = 3, second = 4))
[1] 8
> outer4(-1, 2, list(first = 3, second = 4))
[1] 8