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.
Version snapshots simplify correctness: a complicated command restores the complete prior state, so a bespoke inverse cannot accidentally omit an auxiliary field. Redo restores the recorded result without re-executing behavior that might depend on time, randomness or external input. Restoring an immutable root takes constant time, though refreshing the display can cost more.
The storage comparison depends on the representation. A change-specific record for these elementary edits retains only a few indices and song references. Copying a length- array for each of edits can require storage and copying per edit. A persistent data structure with structural sharing can preserve many versions much more cheaply; balanced path copying can make small edits allocate new entries. Retaining versions also keeps their reachable data alive. Snapshot references are only constant-sized roots, not a guarantee of constant total retained memory. Neither scheme automatically reverses external effects such as playing audio or writing files. The desired undo boundary must be specified.

Articles by others on the same topic (0)

There are currently no matching articles.