[R] Chaining multiple replacement functions in R

Duncan Murdoch murdoch.duncan at gmail.com
Tue Dec 30 12:43:18 CET 2014


On 29/12/2014 4:41 PM, Daniel Gabrieli wrote:
> I cross posted this on Stack Overflow:
> http://stackoverflow.com/questions/27694466/chaining-multiple-replacement-functions-in-r
> 
> 
> I am using R to work with a large JS object (using the library rjsonio). As
> such, I have a lot of nested lists, which are getting somewhat cumbersome
> to work with. I have a simplified example below. I am trying to work with
> this object by creating some form of ‘getter’ and ‘setter’ functions. After
> looking around, I have found a pretty nice ‘getter’ function that recurses
> through the object and returns the value for the first matching label. This
> is especially great because it lends itself to chaining functions together.
> However, I can not figure out a way to get the same effect for a ‘setter’
> function. Any thoughts on how to create a ‘setter’ function that can be
> chained together in a similar fashion?

I haven't worked through the details here so this might not work, but
the assignment function could add extra information saying which part of
the object was modified.  In the example below, "Firstkey" is
app[[c(3,3,1)]], so a function that modified it could attach c(3,3,1) as
an attribute, and later functions that wanted to do more things to it
could start looking there.

I guess the tricky part would be getting rid of that attribute if you
didn't want to pass it along the chain, e.g. the final call shouldn't
return it.

Duncan Murdoch

> 
> #example, simplified, object
> app = list(
>   1,
>   2,
>   d=list(a=123,
>          b=456,
>          list(
>            FirstKey=list(attr1='good stuff', attr2=12345),
>            SecondKey=list(attr1='also good stuff', attr2=4321)
>            )
>          )
>   )
> 
> 
> #Return a function that returns the value
> #associated with first label that matches 'name'
> getByName <- function(name){
>   rmatch <- function(x) {
>     pos <- match(name, names(x))
>     if (!is.na(pos))
>       return(x[[pos]])
>     for (el in x) {
>       if (class(el) == "list") {
>         out <- Recall(el)
>         if (!is.null(out)) return(out)
>       }
>     }
>   }
>   rmatch
> }
> 
> getFirstKey <- getByName("FirstKey")
> getAttr1 <- getByName("attr1")
> getAttr2 <- getByName("attr2")
> 
> #I like that I can chain these functions together
> getAttr1(getFirstKey(app))
> getAttr2(getFirstKey(app))
> 
> # I would like to be able to do something like this
> # But this won't work
> ###    getAttr1(getFirstKey(app)) <- 9876
> 
> # This does work,,, but I loose the ability to chain functions together
> # Closure around a replacement function
> setterKeyAttr <- function(keyName, attr){
>   function(x, value){
>     x$d[[3]][[keyName]][[attr]] <- value
>     x
>   }
> }
> 
> `setFirstKeyAttr2<-` <- setterKeyAttr("FirstKey", "attr2")
> setFirstKeyAttr2(app) <- 22222
> #check the answer is correct
> getAttr2(getFirstKey(app))
> 
> 
> 
> references:
> 
> http://stackoverflow.com/questions/23124096/r-decorator-to-change-both-input-and-output
> 
> http://r.789695.n4.nabble.com/How-to-get-a-specific-named-element-in-a-nested-list-td3037430.html
> 
> http://adv-r.had.co.nz/Functions.html
> 
> 	[[alternative HTML version deleted]]
> 
> ______________________________________________
> R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.
>



More information about the R-help mailing list