简体   繁体   English

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

[英]Use match.call to pass all arguments to other function

From ?match.call :?match.call

match.call is most commonly used in two circumstances: […] To pass most of the call to another function […] match.call最常用于两种情况: […] 将大部分调用传递给另一个函数 […]

After reading that, I expected I could use match.call when I want to pass all arguments of one function to another function without listing these arguments one by one.读完之后,我希望当我想将一个函数的所有参数传递给另一个函数而不一一列出这些参数时,我可以使用match.call

Example: outer1 passes arguments one by one, outer2 uses 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

The first problem arises, when -1 instead of 1 is passed to outer2 :第一个问题出现了,当-1而不是1传递给outer2

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

Question 1 : What is the technical difference between passing -1 instead of 1 ?问题 1 :传递-1而不是1之间的技术区别是什么? I know that我知道

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

but I suppose that the fact that I passed a language object in the second case is not the (only) relevant difference because passing something of type language to argument c works ( typeof(quote(list(first = 3, second = 4))) # language ).但我想我在第二种情况下传递language对象的事实并不是(唯一的)相关差异,因为将类型语言的某些内容传递给参数c有效的( typeof(quote(list(first = 3, second = 4))) # language )。

In order to overcome the problem above, I try to eval all arguments that are of type language :为了克服上述问题,我尝试eval所有类型为language参数:

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

Question 2: The approach in outer3 seems to "work" but are there further pitfalls I need to take into account?问题 2: outer3的方法似乎“有效”,但我还需要考虑其他陷阱吗? (I know that in some cases it might be disadvantageous to evaluate the arguments but for my case this should not be an issue.) (我知道在某些情况下评估论点可能是不利的,但就我而言,这应该不是问题。)

Question 3: I suppose that the desire to pass all arguments to another function is not very uncommon.问题 3:我想将所有参数传递给另一个函数的愿望并不少见。 Is there a better/standard approach than what I did?有没有比我做的更好/标准的方法?

Question 4: Is it advantageous to pass the raw call to the inner function an do the eval stuff there?问题 4:将原始call传递给内部函数并在那里执行eval内容是否有利? Would this be helpful if I would like to have the arguments as local variables in the inner functions (instead of elements of the parsedCall list)?如果我想将参数作为inner函数中的局部变量(而不是parsedCall列表的元素),这会有所帮助吗? Then, the body of inner3 could be identical to the body of inner1 (while with the current solution, I have to replace a+b with parsedCall$a + parsedCall$b ).然后,身体inner3可以是相同的主体inner1 (而与当前的解决方案,我必须更换a+bparsedCall$a + parsedCall$b )。

Regarding your question:关于你的问题:

I suppose that the desire to pass all arguments to another function is not very uncommon.我想将所有参数传递给另一个函数的愿望并不少见。 Is there a better/standard approach than what I did?有没有比我做的更好/标准的方法?

Then I would say this is a more common way to pass the arguments on:然后我会说这是一种更常见的传递参数的方式:

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])
  do.call(inner1, .args)
}

outer3(-1, 2, list(first = 3, second = 4))
#R> [1] 8

outer4(-1, 2, list(first = 3, second = 4))
#R> [1] 8

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM