Hi all: In the course of playing around with other issues, I wrote the following little function that allows functions to keep state and easily replay and update their state.(see comments after): memify <- function(f) { if (is.primitive(f)) { cat("Cannot memify primitive functions.\n") return(NULL) } if (!inherits(f, "function")) stop("Argument must inherit from class 'function'") arglist <- list() structure( function(...) { m <- tryCatch( as.list(match.call(f)[-1]), error = function(e) { warning("Bad function call; cannot update arguments\n") return(NULL) } ) nm <- names(m) hasname <- nm != "" #logical index of named values if (any(hasname)) { if (anyDuplicated(nm, incomparables = "")) warning("Duplicated names in call; only the first will be used.") arglist <<- modifyList(arglist, m[hasname]) ## this is what does the job } do.call(f, modifyList(m, arglist)) }, class = c("memified", class(f))) } Examples: x <- 1:9; y <- runif(9) plt <- memify(plot) x <- 1:9; y <- runif(9) plt(x,y, col = "blue") ## plt "remembers" these arguments; i.e. keeps state plt( type = "b") ## all other arguments as previous plt(col = "red") ## ditto So my question is: Beyond allowing one to easily change/add argument values and replay when there are lots of arguments floating around, which we often use an IDE's editor to do, is there any real use for this? I confess that, like Pygmalion, I have been charmed by this idea, but it could well be useless, By all means feel free to chastise me if so. 1. I am aware that many functions already have "update" methods to "update" their results without re-entering all arguments -- e.g. lattice graphics, glm, etc. 2. Several packages -- rlang and R6 anyway -- but very likely more, do this sort of thing and way more; the price is added complexity, of course. 3. I realize also that keeping state would be a bad idea in many circumstances, e.g. essentially changing documented defaults. Reply privately to praise or bury if you do not think this is of any interest to readers of this list. Publicly is fine, too. If it's dumb it's dumb. Cheers and best wishes for a better new year for us all, Bert Gunter [[alternative HTML version deleted]]
I'm not enthusiastic about nonstandard evaluation and allowing functions to change state data. Currently, I use some of this in my own packages, but I'm planning to remove most of it. But I did have some fun with your function. ---------- plt <- memify (plot) x <- 1:12 y1 <- seq (0, 18,, 12) y2 <- c ( 16.88, 16.04, 13.23, 13.88, 11.85, 9.61, 9.28, 5.81, 7.52, 3.40, 3.37, 0.07) #test 1 plt (x, y1, type="l") #test 2 plt (ylim = c (18, 0) ) #important econometric timeseries analysis plt (y=y2, main="Monthly NZ GDP (Millions)") ---------- Note: This data is not accurate. On Sat, Jan 2, 2021 at 9:20 AM Bert Gunter <bgunter.4567 at gmail.com> wrote:> > Hi all: > > In the course of playing around with other issues, I wrote the following > little function that allows functions to keep state > and easily replay and update their state.(see comments after): > > memify <- function(f) > { > if (is.primitive(f)) { > cat("Cannot memify primitive functions.\n") > return(NULL) > } > if (!inherits(f, "function")) > stop("Argument must inherit from class 'function'") > arglist <- list() > structure( > function(...) { > m <- tryCatch( > as.list(match.call(f)[-1]), > error = function(e) { > warning("Bad function call; cannot update arguments\n") > return(NULL) > } > ) > nm <- names(m) > hasname <- nm != "" #logical index of named values > if (any(hasname)) { > if (anyDuplicated(nm, incomparables = "")) > warning("Duplicated names in call; only the first will be > used.") > arglist <<- modifyList(arglist, m[hasname]) ## this is what > does the job > } > do.call(f, modifyList(m, arglist)) > }, > class = c("memified", class(f))) > } > > Examples: > > x <- 1:9; y <- runif(9) > plt <- memify(plot) > x <- 1:9; y <- runif(9) > plt(x,y, col = "blue") ## plt "remembers" these arguments; i.e. keeps > state > plt( type = "b") ## all other arguments as previous > plt(col = "red") ## ditto > > So my question is: Beyond allowing one to easily change/add argument values > and replay when there are lots of arguments floating around, which we often > use an IDE's editor to do, is there any real use for this? I confess that, > like Pygmalion, I have been charmed by this idea, but it could well be > useless, By all means feel free to chastise me if so. > > 1. I am aware that many functions already have "update" methods to "update" > their results without re-entering all arguments -- e.g. lattice graphics, > glm, etc. > 2. Several packages -- rlang and R6 anyway -- but very likely more, do this > sort of thing and way more; the price is added complexity, of course. > 3. I realize also that keeping state would be a bad idea in many > circumstances, e.g. essentially changing documented defaults. > > Reply privately to praise or bury if you do not think this is of any > interest to readers of this list. Publicly is fine, too. If it's dumb it's > dumb. > > Cheers and best wishes for a better new year for us all, > > Bert Gunter > > [[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.
This would certainly simplify and make more readable some of my code where I create multiple versions of the same plot calling the same function with minor variations of a few of many arguments. Thanks! Peter On Fri, Jan 1, 2021 at 12:20 PM Bert Gunter <bgunter.4567 at gmail.com> wrote:> Hi all: > > In the course of playing around with other issues, I wrote the following > little function that allows functions to keep state > and easily replay and update their state.(see comments after): > > memify <- function(f) > { > if (is.primitive(f)) { > cat("Cannot memify primitive functions.\n") > return(NULL) > } > if (!inherits(f, "function")) > stop("Argument must inherit from class 'function'") > arglist <- list() > structure( > function(...) { > m <- tryCatch( > as.list(match.call(f)[-1]), > error = function(e) { > warning("Bad function call; cannot update arguments\n") > return(NULL) > } > ) > nm <- names(m) > hasname <- nm != "" #logical index of named values > if (any(hasname)) { > if (anyDuplicated(nm, incomparables = "")) > warning("Duplicated names in call; only the first will be > used.") > arglist <<- modifyList(arglist, m[hasname]) ## this is what > does the job > } > do.call(f, modifyList(m, arglist)) > }, > class = c("memified", class(f))) > } > > Examples: > > x <- 1:9; y <- runif(9) > plt <- memify(plot) > x <- 1:9; y <- runif(9) > plt(x,y, col = "blue") ## plt "remembers" these arguments; i.e. keeps > state > plt( type = "b") ## all other arguments as previous > plt(col = "red") ## ditto > > So my question is: Beyond allowing one to easily change/add argument values > and replay when there are lots of arguments floating around, which we often > use an IDE's editor to do, is there any real use for this? I confess that, > like Pygmalion, I have been charmed by this idea, but it could well be > useless, By all means feel free to chastise me if so. > > 1. I am aware that many functions already have "update" methods to "update" > their results without re-entering all arguments -- e.g. lattice graphics, > glm, etc. > 2. Several packages -- rlang and R6 anyway -- but very likely more, do this > sort of thing and way more; the price is added complexity, of course. > 3. I realize also that keeping state would be a bad idea in many > circumstances, e.g. essentially changing documented defaults. > > Reply privately to praise or bury if you do not think this is of any > interest to readers of this list. Publicly is fine, too. If it's dumb it's > dumb. > > Cheers and best wishes for a better new year for us all, > > Bert Gunter > > [[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. >[[alternative HTML version deleted]]