如何处理父函数的参数?

huangapple go评论60阅读模式
英文:

How can I process arguments of parent function?

问题

Sure, here's the translated code you provided:

我有一些在R包中函数的弃用参数。我做了类似这样的事情:

```{r}
foo <- function(x, y, newarg, oldarg) {

   if (!missing("oldarg")) {
      warning("参数已弃用,请使用newarg代替。参数newarg被设置为参数oldarg的值。")
      newarg <- oldarg
   }

 ### 接下来是实际的函数代码...
}

这个讨论可以在这里找到:https://stackoverflow.com/questions/40906200/how-to-deprecate-an-argument

我想通过使用一个函数来使整个包中的处理方式一致,就像这样:

foo <- function(arg1, newarg, oldarg) {

newarg <- myDeprecFun(oldarg, newarg)

 ### 接下来是实际的函数代码...
}

现在我遇到了问题。我已经阅读了http://adv-r.had.co.nz/Environments.html以及书中的其他章节,但我仍然不明白。我尝试了这样的包装器:

myDeprecFun <- deprecatedArg <- function(oldarg, newarg) {
    
    args <- callArgs(-2)
    names.args <- names(args)
    
### 一些操作
    if (oldarg %in% names.args) {
        message(sprintf("%s是一个已弃用的参数。请使用%s代替。", oldarg, newarg))
        return(args[[oldarg]])
    }
    
### 返回newarg
    parent.frame()[[newarg]]
}

其中callArgs是:

callArgs <- function(which = -1) {
    
### 调用中的参数。
    ## 对于这个不需要参数
    args.call <- as.list(
        match.call(
            definition = sys.function(which = which),
            call = sys.call(which = which)
        )
    )[-1]
    
## 获取参数内容
    argsconts <- lapply(args.call, eval, envir = parent.frame(n = -which + 1))
    
    as.list(do.call(c, argsconts))
}

一个问题是在callArgs中的eval调用中我应该跳过多少个环境。我对此非常困惑。如果更容易的话,我可以将调用myDeprecFun()的环境作为参数传递给myDeprecFun(),然后传递给callArgs()。

另一个问题是我不确定callArgs()是否会捕获所有的参数。如果在函数调用中有一些未命名的参数,会怎么样,比如:

foo(a = 1, 3, 4)

在这里,参数2或3可能是一个已弃用的参数。

对于如何构建这样一个函数的任何提示都会非常感激!


<details>
<summary>英文:</summary>

I have some deprecated arguments to functions in an R package. I do something like this:

```{r}
foo &lt;- function(x, y, newarg , oldarg ){

   if (!missing(&quot;oldarg&quot;)){
      warning(&quot;Argument deprecated, use newarg instead. 
              The parameter newarg is set equal the parameter oldarg.&quot;)
      newarg &lt;- oldarg
   }

 ### Then the actual function code....
}

which is being discussed here: https://stackoverflow.com/questions/40906200/how-to-deprecate-an-argument

I'd like to align how this is handled across the package by using a function for it like:

foo &lt;- function(arg1,newarg,oldarg){

newarg &lt;- myDeprecFun(oldarg,newarg)

 ### Then the actual function code....

}

Now I am hitting a wall. I have read through http://adv-r.had.co.nz/Environments.html and other chapters of the book but I still don't get it. I tried a wrapper like this:

myDeprecFun &lt;- deprecatedArg &lt;- function(oldarg,newarg){
    
    args &lt;- callArgs(-2)
    names.args &lt;- names(args)
    
### things like
    if( oldarg %in% names.args ) {
        message(sprintf(&quot;%s is a deprecated argument. Please use %s instead.&quot;,oldarg,newarg))
        return(args[[oldarg]])
    }
    
### return newarg
    parent.frame()[[newarg]]

}

where callArgs is:

callArgs &lt;- function(which=-1){
    
### args in call.
    ## no args are needed for this
    args.call &lt;- as.list(
        match.call(
            definition = sys.function(which=which),
            call = sys.call(which=which)
        )
    )[-1]
    
## get the argument contents
    argsconts &lt;- lapply(args.call, eval, envir = parent.frame(n=-which+1))
    
    as.list(do.call(c,argsconts))
}

One problem is the number of environments I should jump in the eval call in callArgs. I am very confused about that. If easier, it would be fine by me passing the environment in which myDeprecFun() is called as an argument to myDeprecFun() and then to callArgs().

Another problem is I'm not sure callArgs() will capture all arguments. What if some are not named in the function call, like

foo(a=1,3,4)

Here, argument 2 or 3 could be a deprecated argument.

Any hint to how I can construct such a function is very appreciated!

答案1

得分: 0

我会将调用传递给myDeprecFun

foo <- function(arg1, newarg, oldarg){
  
  newarg <- myDeprecFun("oldarg", "newarg", match.call())
  newarg
}

myDeprecFun <- function(oldarg, newarg, thecall) {
  if (oldarg %in% names(thecall)) {
    message(sprintf("%s is a deprecated argument. Please use %s instead.",
                    oldarg, newarg))
    if (newarg %in% names(thecall)) {
      thecall[[newarg]]
    } else {
      thecall[[oldarg]]
    }
  } else {
    thecall[[newarg]]
  }
}

foo(a=1, 3, 4)
#oldarg is a deprecated argument. Please use newarg instead.
#[1] 3
英文:

I would pass the call to myDeprecFun:

foo &lt;- function(arg1,newarg,oldarg){
  
  newarg &lt;- myDeprecFun(&quot;oldarg&quot;, &quot;newarg&quot;, match.call())
  newarg
}

myDeprecFun &lt;- function(oldarg,newarg, thecall) {
  if (oldarg %in% names(thecall)) {
    message(sprintf(&quot;%s is a deprecated argument. Please use %s instead.&quot;,
                    oldarg,newarg))
    if (newarg %in% names(thecall)) {
      thecall[[newarg]]
    } else {
      thecall[[oldarg]]
    }
  } else {
    thecall[[newarg]]
  }
}

foo(a=1,3,4)
#oldarg is a deprecated argument. Please use newarg instead.
#[1] 3

huangapple
  • 本文由 发表于 2023年6月12日 10:14:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/76453297.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定