///|
/// Moves the focus to the first element (start of the list).
pub fn[T] Zipper::move_to_start(self : Zipper[T]) -> Zipper[T] {
match self.move_left() {
Some(next) => next.move_to_start()
None => self
}
}
///|
/// Moves the focus to the last element (end of the list).
pub fn[T] Zipper::move_to_end(self : Zipper[T]) -> Zipper[T] {
match self.move_right() {
Some(next) => next.move_to_end()
None => self
}
}
// Helper function to create a list from an array for easy testing.
///|
pub fn[T] MList::from_array(arr : Array[T]) -> MList[T] {
arr.rev_fold(init=Nil, fn(acc, x) { Cons(x, acc) })
}
///|
/// Creates a zipper from a list, focusing on the first element.
/// Returns `None` if the list is empty.
pub fn[T] Zipper::from_list(list : MList[T]) -> Zipper[T]? {
match list {
Nil => None
Cons(head, tail) => Some({ left: Nil, focus: head, right: tail })
}
}
///|
/// Converts a zipper back into a list.
pub fn[T] Zipper::to_list(self : Zipper[T]) -> MList[T] {
loop (self.left.reverse(), Cons(self.focus, self.right)) {
(Nil, acc) => acc
(Cons(head, tail), acc) => continue (tail, Cons(head, acc))
}
}
///|
/// Returns the element currently in focus.
pub fn[T] Zipper::current(self : Zipper[T]) -> T {
self.focus
}
///|
/// Moves the focus one step to the right.
/// Returns `None` if already at the end of the list.
pub fn[T] Zipper::move_right(self : Zipper[T]) -> Zipper[T]? {
match self.right {
Nil => None
Cons(new_focus, new_right) => {
let new_left = Cons(self.focus, self.left)
Some({ left: new_left, focus: new_focus, right: new_right })
}
}
}
///|
/// Moves the focus one step to the left.
/// Returns `None` if already at the beginning of the list.
pub fn[T] Zipper::move_left(self : Zipper[T]) -> Zipper[T]? {
match self.left {
Nil => None
Cons(new_focus, new_left) => {
let new_right = Cons(self.focus, self.right)
Some({ left: new_left, focus: new_focus, right: new_right })
}
}
}
///|
/// Replaces the focused element with a new value.
pub fn[T] Zipper::update(self : Zipper[T], new_focus : T) -> Zipper[T] {
{ ..self, focus: new_focus }
}
///|
/// Inserts an element to the left of the focus. The new element remains on the left.
pub fn[T] Zipper::insert_left(self : Zipper[T], value : T) -> Zipper[T] {
{ ..self, left: Cons(value, self.left) }
}
///|
/// Inserts an element to the right of the focus. The new element remains on the right.
pub fn[T] Zipper::insert_right(self : Zipper[T], value : T) -> Zipper[T] {
{ ..self, right: Cons(value, self.right) }
}
///|
/// Deletes the focused element.
/// Focus moves to the right if possible, otherwise to the left.
/// Returns `None` if the deletion results in an empty list.
pub fn[T] Zipper::delete(self : Zipper[T]) -> Zipper[T]? {
match self.right {
Cons(new_focus, new_right) =>
Some({ ..self, focus: new_focus, right: new_right })
Nil =>
match self.left {
Cons(new_focus, new_left) =>
Some({ left: new_left, focus: new_focus, right: Nil })
Nil => None
}
}
}