mEditor <- setRefClass("matrixEditor", fields = list( data = "matrix", edits = "list"), methods = list( edit = function(i, j, value) { ## the following string documents the edit method 'Replaces the range [i, j] of the object by value. ' backup <- list(i, j, data[i,j]) data[i,j] <<- value edits <<- c(edits, list(backup)) invisible(value) }, undo = function() { 'Undoes the last edit() operation and update the edits field accordingly. ' prev <- edits if(length(prev)) prev <- prev[[length(prev)]] else stop("No more edits to undo") edit(prev[[1]], prev[[2]], prev[[3]]) ## trim the edits list length(edits) <<- length(edits) - 2 invisible(prev) } )) xMat <- xEdited <- matrix(as.double(1:12),4,3) xEdited[[2,2]] <- 0 xx <- mEditor$new(data = xMat) xx$edit(2, 2, 0) stopifnot(identical(xx$data, xEdited)) xEdited[[1,3]] <- -1 xx$edit(1,3, -1) stopifnot(identical(xx$data, xEdited)) xx$undo() xEdited[[1,3]] <- xMat[[1,3]] stopifnot(identical(xx$data, xEdited)) xx$undo() stopifnot(identical(xx$data, xMat))