I have a general style question about R coding. Suppose I'm writing a function (foo1) that calls other functions (foo2, foo3, ...) which have complicated argument lists (e.g. optim(), plot()), _and_ I may be calling several different functions in the body of foo1. Since foo2 and foo3 have different sets of arguments, I can't just use "..." ; I did write some code a while ago that would look at formals() to dissect out arguments that should be passed to the different functions, but it seemed overly complex. The particular case I have now is a little simpler. foo2 (points3d) and foo3 (spheres3d) are both functions from the rgl package that pass arguments such as color, alpha, etc. along to an rgl.material() command with lots of possible arguments. (The function may also call segments3d or lines3d, but these all have the same arguments as points3d.) However, to change the size of points you use "size"; to change the size of spheres you use "radius". Do I (1) add "radius" to the argument list, cluttering up the argument list for one particular special case? (2) add "size" to the argument list, so that it doesn't become part of "..." and I can say spheres3d(radius=size,...) ? (3) do something like dotlist = list(...) if (type=="s" && !is.null(dotlist$size)) radius <- dotlist$size and pull "size" out of ... myself (and make a note to that effect in the documentation)? (I guess another general solution to this is to ask for lists of arguments, like MoreArgs in mapply(). Another would be to go back and change spheres3d to make size a synonym for radius ... ) any thoughts? Ben Bolker -- 620B Bartram Hall bolker at zoo.ufl.edu Zoology Department, University of Florida http://www.zoo.ufl.edu/bolker Box 118525 (ph) 352-392-5697 Gainesville, FL 32611-8525 (fax) 352-392-3704
On 6/29/2006 12:53 PM, Ben Bolker wrote:> I have a general style question about R coding. > > Suppose I'm writing a function (foo1) that calls other functions > (foo2, foo3, ...) which have complicated argument > lists (e.g. optim(), plot()), _and_ > I may be calling several different functions in the body of > foo1. Since foo2 and foo3 have different sets of arguments, I > can't just use "..." ; I did write some code a while ago that > would look at formals() to dissect out arguments that should > be passed to the different functions, but it seemed overly > complex. > > The particular case I have now is a little simpler. > > foo2 (points3d) and foo3 (spheres3d) > are both functions from the rgl package > that pass arguments such as color, alpha, etc. along to > an rgl.material() command with lots of possible arguments. > (The function may also call segments3d or lines3d, but > these all have the same arguments as points3d.) > However, to change the size of points you use "size"; to > change the size of spheres you use "radius". Do I > (1) add "radius" to the argument list, cluttering up > the argument list for one particular special case? > (2) add "size" to the argument list, so that it doesn't > become part of "..." and I can say spheres3d(radius=size,...) ? > (3) do something like > dotlist = list(...) > if (type=="s" && !is.null(dotlist$size)) radius <- dotlist$size > and pull "size" out of ... myself (and make a note to that > effect in the documentation)? > (I guess another general solution to this is to ask for > lists of arguments, like MoreArgs in mapply(). Another > would be to go back and change spheres3d to make size > a synonym for radius ... )I would do (2) in general, but in this particular case it might not be right. "size" is measured in pixels, and "radius" is measured in data units, so they really are different things. You could try to fiddle it so the radius is set to the right number of units to match the number of pixels that were requested, but users can change the scale pretty easily. Duncan Murdoch
Hi Ben, I have often asked myself such question and often come back to the following additional options: (4) Use '...' and ensure encapsulated functions/calls (foo2 and foo3) also have '...' within their arguments. There is no problem to call 3dspehre with a list of arguments that include both 'radius' and 'size' if (and only if) 3dsphere function argumnts are (radius=,...) so that size will just be ignored. foo1 <- function(...){ foo2(...) foo3(...) } Document that all arguments foo2 can handle could be introduced within a cool to foo1, as well as those foo3 arguments. Only problem/point of detail is case where foo2 and foo3 do share arguments and you would like to distinguish. Then use (5) foo1 <- function(x,foo2Args=list(radius=2), foo3Args=list(size), ...){ do.call("foo2",foo2Args) # or do.call("foo2",c(foo2Args,list(...)) depending on what you prefer } Eric 2006/6/29, Ben Bolker <bolker@zoo.ufl.edu>:> > > I have a general style question about R coding. > > Suppose I'm writing a function (foo1) that calls other functions > (foo2, foo3, ...) which have complicated argument > lists (e.g. optim(), plot()), _and_ > I may be calling several different functions in the body of > foo1. Since foo2 and foo3 have different sets of arguments, I > can't just use "..." ; I did write some code a while ago that > would look at formals() to dissect out arguments that should > be passed to the different functions, but it seemed overly > complex. > > The particular case I have now is a little simpler. > > foo2 (points3d) and foo3 (spheres3d) > are both functions from the rgl package > that pass arguments such as color, alpha, etc. along to > an rgl.material() command with lots of possible arguments. > (The function may also call segments3d or lines3d, but > these all have the same arguments as points3d.) > However, to change the size of points you use "size"; to > change the size of spheres you use "radius". Do I > (1) add "radius" to the argument list, cluttering up > the argument list for one particular special case? > (2) add "size" to the argument list, so that it doesn't > become part of "..." and I can say spheres3d(radius=size,...) ? > (3) do something like > dotlist = list(...) > if (type=="s" && !is.null(dotlist$size)) radius <- dotlist$size > and pull "size" out of ... myself (and make a note to that > effect in the documentation)? > (I guess another general solution to this is to ask for > lists of arguments, like MoreArgs in mapply(). Another > would be to go back and change spheres3d to make size > a synonym for radius ... ) > > any thoughts? > Ben Bolker > > > -- > 620B Bartram Hall bolker@zoo.ufl.edu > Zoology Department, University of Florida http://www.zoo.ufl.edu/bolker > Box 118525 (ph) 352-392-5697 > Gainesville, FL 32611-8525 (fax) 352-392-3704 > > ______________________________________________ > R-devel@r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel >-- Eric Lecoutre Consultant - Business & Decision Business Intelligence & Customer Intelligence [[alternative HTML version deleted]]
Here is an approach. fn.dots takes a character string, fn.name, such as a function name and a named list, dots. If fn.name is "f", say, then it returns all components of dots whose name is of the form f.somestring removing the f. prefix as well as components containing unprefixed strings. It would typically be used like this: f.dots <- fn.dots("f", dots) do.call("f", f.dots) and the user can specify that x be passed to all functions by naming it x, to just f by naming it f.x. If both x and f.x appears then f.x takes precedence in a call to f. fn.dots <- function(fn.name, dots) { pat <- paste("^", fn.name, "[.]", sep = "") nm <- names(dots) fn.nm <- grep(pat, nm, value = TRUE) dots[sub(pat, "", fn.nm)] <- dots[fn.nm] dots[grep("^[^.]*[.]", nm, value = TRUE)] <- NULL dots } dots <- list(a = 33, f.a = 55, g.a = 44, b = 56, g.c = 99) fn.dots("f", dots) # list(a = 55, b = 56) fn.dots("g", dots) # list(a = 44, b = 56, c = 99) fn.dots("h", dots) # list(a = 33, b = 56) On 6/29/06, Ben Bolker <bolker at zoo.ufl.edu> wrote:> > I have a general style question about R coding. > > Suppose I'm writing a function (foo1) that calls other functions > (foo2, foo3, ...) which have complicated argument > lists (e.g. optim(), plot()), _and_ > I may be calling several different functions in the body of > foo1. Since foo2 and foo3 have different sets of arguments, I > can't just use "..." ; I did write some code a while ago that > would look at formals() to dissect out arguments that should > be passed to the different functions, but it seemed overly > complex. > > The particular case I have now is a little simpler. > > foo2 (points3d) and foo3 (spheres3d) > are both functions from the rgl package > that pass arguments such as color, alpha, etc. along to > an rgl.material() command with lots of possible arguments. > (The function may also call segments3d or lines3d, but > these all have the same arguments as points3d.) > However, to change the size of points you use "size"; to > change the size of spheres you use "radius". Do I > (1) add "radius" to the argument list, cluttering up > the argument list for one particular special case? > (2) add "size" to the argument list, so that it doesn't > become part of "..." and I can say spheres3d(radius=size,...) ? > (3) do something like > dotlist = list(...) > if (type=="s" && !is.null(dotlist$size)) radius <- dotlist$size > and pull "size" out of ... myself (and make a note to that > effect in the documentation)? > (I guess another general solution to this is to ask for > lists of arguments, like MoreArgs in mapply(). Another > would be to go back and change spheres3d to make size > a synonym for radius ... ) > > any thoughts? > Ben Bolker > > > -- > 620B Bartram Hall bolker at zoo.ufl.edu > Zoology Department, University of Florida http://www.zoo.ufl.edu/bolker > Box 118525 (ph) 352-392-5697 > Gainesville, FL 32611-8525 (fax) 352-392-3704 > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel >