If sequence versions are immutable, replace perform by the following method; the insert, delete and move entry points can stay as written:
private def perform(forward: () => Unit,
                    backward: () => Unit): Change = {
  val before = songs
  forward()
  val after = songs
  new Change {
    def undo(): Unit = { songs = before }
    def redo(): Unit = { songs = after }
  }
}
The unused inverse argument can subsequently be removed from perform and its callers. Each history record now captures two complete versions. Undo and redo restore the respective roots without replaying an operation, an instance of the Memento pattern. The same chronological history discipline still applies.
The supplied method signatures alone do not establish immutability or persistence. If insert or delete changes a shared mutable software object, merely storing its reference fails to freeze the earlier state. Then independent copies of the relevant state are needed, including any mutable song state intended to be undoable, or the implementation must provide immutable persistent data structure versions. This is a representation requirement, not a reason to invent a particular unavailable copying API.

Articles by others on the same topic (0)

There are currently no matching articles.