= Solution
Replace edit-specific inverse information by before/after snapshots implementing the <Memento pattern>. The same `Change` and `History` interfaces still work. A complete alternative suite is:
``
class SnapshotSlideSuite(initial: Sequence[Slide]) {
private var slides = initial
private def changeTo(after: Sequence[Slide]): Change = {
val before = slides
slides = after
new Change {
def undo(): Unit = { slides = before }
def redo(): Unit = { slides = after }
}
}
def insert(i: Int, x: Slide): Change =
changeTo(slides.insert(i, x))
def delete(i: Int): Change =
changeTo(slides.delete(i))
def move(from: Int, to: Int): Change = {
val x = slides.elementAt(from)
changeTo(slides.delete(from).insert(to, x))
}
}
``
By-value evaluation computes `after` without changing `slides`, then `changeTo` captures the still-current `before` and installs the new value. The `val` bindings inside each call are stable snapshots, rather than later reads of a mutable variable. Under the same chronological history <preconditions>, \b[undo and redo are constant-time reference assignments]. This is the <Memento pattern> applied to an immutable <sequence>. Retaining a reference to an in-place-mutated <sequence> would not save its old state. The snapshot covers slide order and membership; it does not promise to undo unrelated mutations inside a `Slide` object.
Back to article page