From Mark.Bravington at csiro.au  Wed Sep 20 02:54:15 2006
From: Mark.Bravington at csiro.au (Mark.Bravington at csiro.au)
Date: Wed, 20 Sep 2006 10:54:15 +1000
Subject: [Rd] An update method for lists?
Message-ID: <D79013E40FEF254AAF0D72DFC94F27482306C0@extas4-hba.tas.csiro.au>

> 
> On 9/19/06, Gabor Grothendieck <ggrothendieck at gmail.com> wrote:
> > Perhaps it should have another name, be made generic and 
> extended to 
> > functions in which case it would work on the formal arguments.  e.g.
> >
> >    read.table.comma <- modify(read.table, list(sep = ","))
> >
> > would return a function that is the same as read.table but 
> has "," as 
> > the default for sep.
> >
> > Python has something like this called partial:
> >    http://docs.python.org/dev/whatsnew/pep-309.html
> 
> I have had similar thoughts, and even requested a variant a 
> while back, with a possible implementation:

There is a function that does this in the 'mvbutils' package, called
'hack':

hack <- function( fun, ...){
  mc <- match.call( expand.dots=FALSE)$...
  for( i in names( mc))
    formals( fun)[[ i]] <- mc[[ i]]
  fun
}

which is a little different to Deepayan's version-- not sure what the
pros & cons of each are. I use 'hack' extensively inside my '.First'
(and in the startup code for 'mvbutils' itself) to change default
parameters in various 'base', 'graphics' and 'utils' functions. Sounds
like this may be fairly common practice.

Mark

Mark Bravington
CSIRO Mathematical & Information Sciences
Marine Laboratory
Castray Esplanade
Hobart 7001
TAS

ph (+61) 3 6232 5118
fax (+61) 3 6232 5012
mob (+61) 438 315 623

> 
> https://stat.ethz.ch/pipermail/r-devel/2006-March/036696.html
> 
> Again, the main question is whether it makes sense to 
> introduce this in `one of the base packages'.
> 
> -Deepayan

> 
> > On 9/18/06, Deepayan Sarkar <deepayan.sarkar at gmail.com> wrote:
> > > On 9/15/06, Deepayan Sarkar <deepayan.sarkar at gmail.com> wrote:
> > > > On 9/15/06, Martin Maechler <maechler at stat.math.ethz.ch> wrote:
> > > > > >>>>> "DeepS" == Deepayan Sarkar <deepayan.sarkar at gmail.com>
> > > > > >>>>>     on Fri, 15 Sep 2006 12:22:15 -0700 writes:
> > > > >
> > > > >     DeepS> Hi, since lattice uses nested lists in various
> > > > >     DeepS> situations, it has had an unexported 
> function called
> > > > >     DeepS> updateList for a while, which looks like
> > > > >
> > > > >  >>     > lattice:::updateList
> > > > >  >>     function (x, val)
> > > > >  >>     {
> > > > >  >>     if (is.null(x))
> > > > >  >>         x <- list()
> > > > >  >>     if (!is.list(x))
> > > > >  >>         stop("x must be NULL or a list")
> > > > >  >>     if (!is.list(val))
> > > > >  >>         stop("val must be a list")
> > > > >  >>     xnames <- names(x)
> > > > >  >>     for (v in names(val)) {
> > > > >  >>         existing <- v %in% xnames
> > > > >  >>         if (existing && is.list(x[[v]]) && 
> is.list(val[[v]]))
> > > > >  >>             x[[v]] <- updateList(x[[v]], val[[v]])
> > > > >  >>         else x[[v]] <- val[[v]]
> > > > >  >>     }
> > > > >  >>     x
> > > > >  >>     }
> > > > >
> > > > > [I'm not sure I'd allow NULL for 'x';  typing list() 
> instead of  
> > > > > NULL is not much more, but when the function name 
> even includes  'list'
> > > > >  I'd really require a list for 'x']
> > > >
> > > > Makes sense.
> > > >
> > > > > You could hence collapse the first 6 lines to the single
> > > > >
> > > > >    stopifnot(is.list(x), is.list(val))
> > > >
> > > > I'll check if lattice needs some fixes with this.
> > >
> > > Actually, I do need to allow NULL, because update.trellis does 
> > > things like
> > >
> > > update.trellis <- function(object, ..., par.strip.text, ...) {
> > >    ...
> > >    object$par.strip.text <- 
> updateList(object$par.strip.text, par.strip.text)
> > >    ...
> > > }
> > >
> > > where object$par.strip.text may be initially NULL. But 
> I'll do that 
> > > inside a lattice wrapper.
> > >
> > > > >     DeepS> Basically, it recursively replaces 
> elements that have
> > > > >     DeepS> been specified in val, leaving the other components
> > > > >     DeepS> alone. I'm not aware of any other actual situation
> > > > >     DeepS> where this is useful, but it certainly can be, so I
> > > > >     DeepS> want to export this functionaliy. At least 
> one other
> > > > >     DeepS> person (Gabor) has also asked for that.
> > > > >
> > > > > I've had a similar need only recently:
> > > > > If a list is used to store "defaults" and you want a 
> safe way to 
> > > > > change only a few of the values...
> > > > > I presume you use this for manipulating the settings 
> of lattice 
> > > > > parts ?
> > > >
> > > > Yes, it's primarily used inside trellis.par.set, but 
> many other places as well.
> > > >
> > > > >     DeepS> Now, as the name suggests, I think it might be
> > > > >     DeepS> reasonable to export this as an update method for
> > > > >     DeepS> "list" objects. Depending on what others (in
> > > > >     DeepS> particular r-core) think, one of these things might
> > > > >     DeepS> happen:
> > > > >
> > > > >     DeepS> (1) I export it as updateList (or some 
> other name) in lattice
> > > > >     DeepS> (2) I export it as an S3 method 
> update.list in lattice
> > > > >     DeepS> (3) It gets added as an S3 method 
> update.list in one 
> > > > > of the base packages or
> > > > >     (4) it gets added as utility function updateList() to
> > > > >         'utils' {= one of the base packages}
> > > >
> > > > Yes, that a good option too (certainly better than (1))
> > > >
> > > > > which I'd favor momentarily.
> > > > > - update() is typically for updating *models*
> > > > > - it's not clear that this is *the* method for update()ing a 
> > > > > list
> > > >
> > > > I agree. Part of the reason I brought this up is 
> because it is not 
> > > > clear to me what justifies a new method for an existing 
> generic. 
> > > > An argument for is that one doesn't introduce yet another 
> > > > function, which (I thought) might be enough if the 
> other choice is 
> > > > to not have any method at all.
> > > >
> > > > > I'm also a bit wondering if it wouldn't make sense to 
> change the 
> > > > > name to something like assignInList().
> > > >
> > > > I'm open to suggestions for the name. I didn't think too much 
> > > > about it since it was unexported anyway.
> > > >
> > > > >     DeepS> The default option is (1), and I guess 
> Sept 19 is the deadline for any
> > > > >     DeepS> of these to be included in R 2.4.0.
> > > > >
> > > > > Yes, that's true for (3) & (4) are higher if you 
> provide a patch 
> > > > > to R-devel (not R-alpha) which includes a man page ...  [but 
> > > > > don't hurry, I'd like to see other comments]
> > >
> > > I have checked in
> > >
> > > https://svn.r-project.org/R-packages/trunk/lattice/R/modifyList.R
> > > 
> https://svn.r-project.org/R-packages/trunk/lattice/man/modifyList.Rd
> > >
> > > which I'm happy to offer for inclusion in utils or wherever might 
> > > seem appropriate. I'll upload a version of lattice which includes 
> > > these late tomorrow if I don't see any more comments by then.
> > >
> > > I've changed the name because I wasn't sure if 
> assignInList might be 
> > > confusing, as the semantics are different from those of assign 
> > > (assign is like 'fix', while this is more like 'edit'). 
> However, any 
> > > name is fine with me.
> > >
> > > Deepayan
> 
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
> 
>




[Rd] An update method for lists?
Mark.Bravington at csiro.au