How to deal with ellipsis (…) in the presence of optional arguments?

好久不见. 提交于 2019-12-07 10:06:41

问题


I have a problem with ellipsis when I use optional arguments in my function definition. To clarify, I define following functions:

func1 <- function (x) (x-2)^2

func3 <- function (fun, arg.curve.user){
  arg.curve.user$expr <-  substitute(func1)
  arg.curve.default <- list(col = "blue", n = 1000, main = "This is a test")
  arg.curve <- modifyList (arg.curve.default, arg.curve.user)
  do.call("curve", arg.curve)
}

# optimizes func1 and call func2 to plot func1
func2 <- function (lb, ub, n.restarts = 5, n.sim = 10, ...){
  arg.curve.user <- as.list(substitute(list(...)))
  output <- gosolnp(fun = func1, LB = lb, UB = ub,  n.restarts =  n.restarts, 
  n.sim =  n.sim)$par
  func3(fun = func1, arg.curve.user = arg.curve.user)
   return(output)
}

By calling func2, func1 is optimized and also plotted through a func3 call (package Rsolnp is required).

func2 ( lb = 0, ub = 8, n.restarts = 5, n.sim = 10, n = 200, from = 0, to = 8)

But suppose a user misspells n.restarts and writes nrestarts:

func2 ( lb = 0, ub = 8, nrestarts = 5, n.sim = 10, n = 200, from = 0, to = 8)

In this case, I expects R to implement the following plans to deal with absence of n.restarts:

  1. assigns default value, i.e. 5, to n.restarts as an optional argument
  2. declares a warning at the end: "nrestarts" is not a graphical parameter

But this does not happen and R assigns value of n (200) to n.restarts instead!!

Can anyone help me to fix this problem?

Many thanks


回答1:


It is partial matching the n argument to n.restarts when one is not supplied by the user. Instead, and contrary to the advice of @Andrie (which will work, of course), there is a mechanism that allows you to continue in the manner you have with an argument n and and argument n.restarts. The trick is to place arguments you want to match exactly after the ....

func2 <- function (lb, ub, ..., n.restarts = 5, n.sim = 10){
  writeLines(paste("Value of `n.restarts` is", n.restarts))
  arg.curve.user <- as.list(substitute(list(...)))
  output <- gosolnp(fun = func1, LB = lb, UB = ub,  n.restarts =  n.restarts, 
                    n.sim =  n.sim)$par
  func3(fun = func1, arg.curve.user = arg.curve.user)
  output
}

In use this gives:

> func2 (lb = 0, ub = 8, n.restarts = 2, n.sim = 10, n = 200,
+        from = 0, to = 8)
Value of `n.restarts` is 2          <---- Here!

Iter: 1 fn: 6.926e-15    Pars:  2.00000
Iter: 2 fn: 2.501e-15    Pars:  2.00000
solnp--> Completed in 2 iterations

Iter: 1 fn: 8.336e-16    Pars:  2.00000
Iter: 2 fn: 8.336e-16    Pars:  2.00000
solnp--> Completed in 2 iterations
[1] 2
> func2 (lb = 0, ub = 8, nrestarts = 2, n.sim = 10, n = 200,
+        from = 0, to = 8)
Value of `n.restarts` is 5          <---- Here! Default

Iter: 1 fn: 2.83e-15     Pars:  2.00000
Iter: 2 fn: 2.5e-15  Pars:  2.00000
solnp--> Completed in 2 iterations

Iter: 1 fn: 2.037e-15    Pars:  2.00000
Iter: 2 fn: 2.037e-15    Pars:  2.00000
solnp--> Completed in 2 iterations

Iter: 1 fn: 1.087e-15    Pars:  2.00000
Iter: 2 fn: 1.087e-15    Pars:  2.00000
solnp--> Completed in 2 iterations

Iter: 1 fn: 8.558e-16    Pars:  2.00000
Iter: 2 fn: 8.558e-16    Pars:  2.00000
solnp--> Completed in 2 iterations

Iter: 1 fn: 7.147e-16    Pars:  2.00000
Iter: 2 fn: 7.147e-16    Pars:  2.00000
solnp--> Completed in 2 iterations
[1] 2
Warning messages:
1: In plot.window(...) : "nrestarts" is not a graphical parameter
2: In plot.xy(xy, type, ...) : "nrestarts" is not a graphical parameter
3: In axis(side = side, at = at, labels = labels, ...) :
  "nrestarts" is not a graphical parameter
4: In axis(side = side, at = at, labels = labels, ...) :
  "nrestarts" is not a graphical parameter
5: In box(...) : "nrestarts" is not a graphical parameter
6: In title(...) : "nrestarts" is not a graphical parameter



回答2:


If you stick with regular argument evaluation you are more likely to get warnings off the bat. Again, you don't need to use special evaluation to get the behaviour that you want. Using non-standard evaluation is a bad idea as you are unlikely to exactly reproduce R's default behaviour, causing subtle bugs for you and your users.

library(Rsolnp)

func1 <- function (x) (x-2)^2

func3 <- function (fun, col = "blue", n = 1000, main = "This is a test", ...){
  curve(func1, ..., n = n, col = col, main = main)
}

# optimizes func1 and call func2 to plot func1
func2 <- function (lb, ub, n.restarts = 5, n.sim = 10, ...){
  output <- gosolnp(fun = func1, LB = lb, UB = ub, n.restarts = n.restarts, 
  n.sim =  n.sim)$par
  func3(fun = func1, ...)
  return(output)
}

Then when you run:

func2 ( lb = 0, ub = 8, nrestarts = 5, n.sim = 10, n = 200, from = 0, to = 8)

you get warnings along the lines of

Warning messages:
1: In plot.window(...) : "nrestarts" is not a graphical parameter
2: In plot.xy(xy, type, ...) : "nrestarts" is not a graphical parameter
3: In axis(side = side, at = at, labels = labels, ...) :
  "nrestarts" is not a graphical parameter
4: In axis(side = side, at = at, labels = labels, ...) :
  "nrestarts" is not a graphical parameter
5: In box(...) : "nrestarts" is not a graphical parameter
6: In title(...) : "nrestarts" is not a graphical parameter


来源:https://stackoverflow.com/questions/14334322/how-to-deal-with-ellipsis-in-the-presence-of-optional-arguments

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!