Martin Maechler
2002-Dec-17 19:08 UTC
[Rd] Changing "..." inside a function: impossible? desirable?
This is was something like a request for your comments, thoughts on the topic... Many of you will know that the "..." (aka \dots) argument is very useful for passing ``further graphical parameters'', but can be a pain when itself is passed to too many plotting functions inside your own function. An artificial example being myplot <- function(x,y, ...) { plot(0:1, 0:1, type = "n", axes = FALSE) result <- <<do stuff with x,y>> points(result, ...) axis(1, ...) axis(2, ...) title(...) } It's clear that some things in "..." can be passed to title() and some to axis(), etc. Of course the above is really silly, but I have a situation where I'd like to see if something, say, `myarg' is part of "..." {piece of cake easy, see below} but then I want to *eliminate* it from "..." such that I can pass "..." down to other functions which would want to see a `myarg' argument. Something like if("myarg" %in% (naml <- names(list(...)))) { ## ok, it's there, take it out marg <- list(...)$ marg ## what I now would like is ... <- unlist( list(...)["myarg" != naml] ) } BTW: one relatively ugly workaround is to use the above *list* say nlist <- list(...)["myarg" != naml] and do all subsequent call where I'd had "..." as do.call( <funname> , c(list( <<other args to funnname>> ), nlist)) but this really obfuscates the code horrendously. PS: I know that using a pars = list(.) argument instead of "..." is another alternative (that we have been using) as well, but lets assume this can't be done, because of compatibility reasons. Martin Maechler <maechler@stat.math.ethz.ch> http://stat.ethz.ch/~maechler/ Seminar fuer Statistik, ETH-Zentrum LEO C16 Leonhardstr. 27 ETH (Federal Inst. Technology) 8092 Zurich SWITZERLAND phone: x-41-1-632-3408 fax: ...-1228 <><
Luke Tierney
2002-Dec-17 22:16 UTC
[Rd] Changing "..." inside a function: impossible? desirable?
On Tue, 17 Dec 2002, Martin Maechler wrote:> > It's clear that some things in "..." can be passed to title() and > some to axis(), etc. > Of course the above is really silly, but I have a situation > where I'd like to see if something, say, `myarg' is part of "..." > {piece of cake easy, see below} but then I want to *eliminate* > it from "..." such that I can pass "..." down to other functions > which would want to see a `myarg' argument. > > Something like > > if("myarg" %in% (naml <- names(list(...)))) { > ## ok, it's there, take it out > marg <- list(...)$ marg > > ## what I now would like is > > ... <- unlist( list(...)["myarg" != naml] ) > } >Does'nt function(x, y, myarg, ...) { if(! missing(myarg)) { ## ok, it's there, do whatever } .... i.e. just remove the things you explicitly want not in ... by naming them as arguments work for your setting? luke -- Luke Tierney University of Iowa Phone: 319-335-3386 Department of Statistics and Fax: 319-335-3017 Actuarial Science 241 Schaeffer Hall email: luke@stat.uiowa.edu Iowa City, IA 52242 WWW: http://www.stat.uiowa.edu
Warnes, Gregory R
2002-Dec-17 22:33 UTC
[Rd] Changing "..." inside a function: impossible? desirable?
I agree that it would be useful to be able to manipulate the contents of <...>. Perhaps syntax like: dots <- dotargs() # equivalent to dots <- list(...) val1 <- dotargs('arg1') to extract the contents of <...> and dotargs('arg1') <- val1 to modifiy the argument 'arg1' would do the trick. Then one could do things like myplot <- function(x,y, ...) { plot(0:1, 0:1, type = "n", axes = FALSE) result <- <<do stuff with x,y>> points(result, ...) dotargs('pch') <- NA axis(1, ...) axis(2, ...) dotargs('lwd') <- dotargs('xaxp') <- dotartgs('yaxp') <- NULL title(...) } -Greg> -----Original Message----- > From: Martin Maechler [mailto:maechler@stat.math.ethz.ch] > Sent: Tuesday, December 17, 2002 1:07 PM > To: R-devel@stat.math.ethz.ch > Subject: [Rd] Changing "..." inside a function: impossible? desirable? > > > This is was something like a request for your comments, thoughts > on the topic... > > Many of you will know that the "..." (aka \dots) argument is > very useful for passing ``further graphical parameters'', > but can be a pain when itself is passed to too many plotting > functions inside your own function. > An artificial example being > > myplot <- function(x,y, ...) { > > plot(0:1, 0:1, type = "n", axes = FALSE) > > result <- <<do stuff with x,y>> > > points(result, ...) > axis(1, ...) > axis(2, ...) > title(...) > } > > It's clear that some things in "..." can be passed to title() and > some to axis(), etc. > Of course the above is really silly, but I have a situation > where I'd like to see if something, say, `myarg' is part of "..." > {piece of cake easy, see below} but then I want to *eliminate* > it from "..." such that I can pass "..." down to other functions > which would want to see a `myarg' argument. > > Something like > > if("myarg" %in% (naml <- names(list(...)))) { > ## ok, it's there, take it out > marg <- list(...)$ marg > > ## what I now would like is > > ... <- unlist( list(...)["myarg" != naml] ) > } > > > BTW: one relatively ugly workaround is to use the above *list* > say nlist <- list(...)["myarg" != naml] > and do all subsequent call where I'd had "..." as > do.call( <funname> , c(list( <<other args to funnname>> > ), nlist)) > but this really obfuscates the code horrendously. > > PS: > I know that using a pars = list(.) argument instead of "..." > is another alternative (that we have been using) as well, > but lets assume this can't be done, because of > compatibility reasons. > > Martin Maechler <maechler@stat.math.ethz.ch>http://stat.ethz.ch/~maechler/ Seminar fuer Statistik, ETH-Zentrum LEO C16 Leonhardstr. 27 ETH (Federal Inst. Technology) 8092 Zurich SWITZERLAND phone: x-41-1-632-3408 fax: ...-1228 <>< ______________________________________________ R-devel@stat.math.ethz.ch mailing list http://www.stat.math.ethz.ch/mailman/listinfo/r-devel LEGAL NOTICE\ Unless expressly stated otherwise, this message is ... [[dropped]]
Philippe Grosjean
2002-Dec-18 15:32 UTC
[Rd] Changing "..." inside a function: impossible? desirable?
Martin, I am also fighting with this kind of problem. I consider it is logical to "specialize" arguments as soon as they have to be used for different features in the plot (col => col.axis, col.title, etc). For instance, imagine one wants to create a simple function to plot two series on the same graph: dualplot <- function(x, y1, y2, ...){ plot(x, y1, ...) lines(x, y2, ...) } # with for instance: X <- 1:20 Y1 <- rnorm(20) Y2 <- runif(20) dualplot(X, Y1, Y2) # so far, so good, but now, if one wants to change color of the second plot separately. Using: dualplot(X, Y1, Y2, col=2) # ... changes color of BOTH plots! # Here, it makes sens to use different arguments for the color of both plots: dualplot2 <- function(x, y1, y2, col1=1, col2=3, ...){ plot(x, y1, col=col1, ...) lines(x, y2, col=col2, ...) } dualplot2(X, Y1, Y2, col1=2, col2=4) # Or better yet, but requires additional code: dualplot3 <- function(x, y1, y2, cols=c(1, 3), ...){ cols <- rep(cols, length.out=3) # For correct recycling rule plot(x, y1, col=cols[1], ...) lines(x, y2, col=cols[2], ...) } dualplot3(X, Y1, Y2, cols=c(2, 4)) # This could also apply for title(), axis(),... of course # The only problem is when one wants to specialize the argument for one subfunction only, but not for the other ones: dualplot4 <- function(x, y1, y2, col2=3, ...){ # We want to use the standard 'col=' argument in the ... for plot(), and a specialized 'col2=' arg for lines() plot(x, y1, ...) lines(x, y2, col=col2, ...) } dualplot4(X, Y1, Y2, col=2, col2=4) # This gives an error of multiple arguments matching in lines()! So, with this approach, we see that the only required change is to give priority to argument 'col=col2' against what could be provided in '...'. Eliminating 'col=' argument in ... is one solution, but the next one is perhaps better. The alternative solution would be to add an option like 'allow.multiple.args.match', set to FALSE by default, but when set to TRUE, only the first match of an argument is used without error message. So, our dualplot4() function would work with: dualplot4 <- function(x, y1, y2, col2=3, ){ plot(x, y1, ...) options(allow.multiple.args.match = TRUE) lines(x, y2, col=col2, ...) # ... other treatment susceptible to have multiple matches options(allow.multiple.args.match = FALSE) } Best, Philippe ...........]<(({?<...............<?}))><............................... ( ( ( ( ( ) ) ) ) ) Philippe Grosjean ( ( ( ( ( ) ) ) ) ) IFREMER Nantes - DEL/AO ( ( ( ( ( rue de l'Ile d'Yeu, BP 21105, 44311 Nantes Cedex 3 ) ) ) ) ) tel: (33) 02.40.37.42.29, fax: (33) 02.40.37.42.41 ( ( ( ( ( ) ) ) ) ) SciViews project coordinator (http://www.sciviews.org) ( ( ( ( ( e-mail: phgrosjean@sciviews.org ) ) ) ) ) ( ( ( ( ( "I'm 100% confident that p is between 0 and 1" ) ) ) ) ) L. Gonick & W. Smith (1993) ....................................................................... -----Message d'origine----- De : r-devel-admin@stat.math.ethz.ch [mailto:r-devel-admin@stat.math.ethz.ch]De la part de Martin Maechler Envoye : mardi 17 decembre 2002 19:07 A : R-devel@stat.math.ethz.ch Objet : [Rd] Changing "..." inside a function: impossible? desirable? This is was something like a request for your comments, thoughts on the topic... Many of you will know that the "..." (aka \dots) argument is very useful for passing ``further graphical parameters'', but can be a pain when itself is passed to too many plotting functions inside your own function. An artificial example being myplot <- function(x,y, ...) { plot(0:1, 0:1, type = "n", axes = FALSE) result <- <<do stuff with x,y>> points(result, ...) axis(1, ...) axis(2, ...) title(...) } It's clear that some things in "..." can be passed to title() and some to axis(), etc. Of course the above is really silly, but I have a situation where I'd like to see if something, say, `myarg' is par t of "..." {piece of cake easy, see below} but then I want to *eliminate* it from "..." such that I can pass "..." down to other functions which would want to see a `myarg' argument. Something like if("myarg" %in% (naml <- names(list(...)))) { ## ok, it's there, take it out marg <- list(...)$ marg ## what I now would like is ... <- unlist( list(...)["myarg" != naml] ) } BTW: one relatively ugly workaround is to use the above *list* say nlist <- list(...)["myarg" != naml] and do all subsequent call where I'd had "..." as do.call( <funname> , c(list( <<other args to funnname>> ), nlist)) but this really obfuscates the code horrendously. PS: I know that using a pars = list(.) argument instead of "..." is another alternative (that we have been using) as well, but lets assume this can't be done, because of compatibility reasons. Martin Maechler <maechler@stat.math.ethz.ch> http://stat.ethz.ch/~maechler/ Seminar fuer Statistik, ETH-Zentrum LEO C16 Leonhardstr. 27 ETH (Federal Inst. Technology) 8092 Zurich SWITZERLAND phone: x-41-1-632-3408 fax: ...-1228 <>< ______________________________________________ R-devel@stat.math.ethz.ch mailing list http://www.stat.math.ethz.ch/mailman/listinfo/r-devel