diff --git a/deque/README.md b/deque/README.md index 769baf0bf..612c99f4a 100644 --- a/deque/README.md +++ b/deque/README.md @@ -90,6 +90,17 @@ dq.front() // Some(2) dq.length() // 3 ``` +If you only want to pop an element without getting the return value, you can use `pop_front_exn()` with `pop_back_exn()`. +These two functions will panic if the queue is empty. + +```moonbit +let dq = Deque::[1, 2, 3, 4, 5] +dq.pop_front_exn() +dq.front() // Some(2) +dq.pop_back_exn() +dq.back() // Some(3) +``` + ### Clear You can use `clear` to clear a deque. But note that the memory it already occupies does not change. @@ -122,12 +133,15 @@ deque supports vector-like `iter/iteri/map/mapi` functions and their inverse for dq.mapi(fn(i, elem) { elem + i }) ``` -### TODO List +### Search & Contains + +You can use `contains()` to find out if a value is in the deque, or `search()` to find its index in the deque. + +```moonbit +let dq = Deque::[1, 2, 3, 4, 5] +dq.contains(1) // true +dq.contains(6) // false +dq.search(1) // Some(0) +dq.search(6) // None +``` -- [ ] fold/foldr -- [ ] reverse -- [ ] contains -- [ ] search -- [ ] swap -- [ ] resize -- [ ] fill diff --git a/deque/deque.mbt b/deque/deque.mbt index 578125bbd..44b0fdb3c 100644 --- a/deque/deque.mbt +++ b/deque/deque.mbt @@ -164,6 +164,38 @@ pub fn push_back[T](self : Deque[T], value : T) -> Unit { self.len += 1 } +/// Removes a fornt element from a deque. +/// +/// Panics if the deque is empty. +/// # Example +/// ``` +/// let dq = Deque::[1, 2, 3, 4, 5] +/// dq.pop_front_exn() +/// ``` +pub fn pop_front_exn[T](self : Deque[T]) -> Unit { + if self.len == 0 { + abort("The deque is empty!") + } + self.head = if self.head < self.buf.length() - 1 { self.head + 1 } else { 0 } + self.len -= 1 +} + +/// Removes a back element from a deque. +/// +/// Panics if the deque is empty. +/// # Example +/// ``` +/// let dq = Deque::[1, 2, 3, 4, 5] +/// dq.pop_back_exn() +/// ``` +pub fn pop_back_exn[T](self : Deque[T]) -> Unit { + if self.len == 0 { + abort("The deque is empty!") + } + self.tail = if self.tail > 0 { self.tail - 1 } else { self.buf.length() - 1 } + self.len -= 1 +} + /// Removes a fornt element from a deque and returns it, or `None` if it is empty. /// /// # Example @@ -228,9 +260,11 @@ test "push_and_pop" { /// println(dq[2]) // 3 /// ``` pub fn op_get[T](self : Deque[T], index : Int) -> T { - if index >= self.len { + if index < 0 || index >= self.len { let len = self.len - abort("index out of bounds: the len is \(len) but the index is \(index)") + abort( + "index out of bounds: the len is from 0 to \(len) but the index is \(index)", + ) } if self.head + index < self.buf.length() { self.buf[self.head + index] @@ -263,9 +297,11 @@ test "op_get" { /// println(dq[2]) // 1 /// ``` pub fn op_set[T](self : Deque[T], index : Int, value : T) -> Unit { - if index >= self.len { + if index < 0 || index >= self.len { let len = self.len - abort("index out of bounds: the len is \(len) but the index is \(index)") + abort( + "index out of bounds: the len is from 0 to \(len) but the index is \(index)", + ) } if self.head + index < self.buf.length() { self.buf[self.head + index] = value @@ -317,8 +353,8 @@ test "iter" { test "iter2" { let v = Deque::[1, 2, 3, 4, 5] - v.pop_front() |> ignore - v.pop_back() |> ignore + v.pop_front_exn() + v.pop_back_exn() let mut sum = 0 v.iter(fn { x => sum += x }) @assertion.assert_eq(sum, 9)? @@ -489,3 +525,51 @@ test "is_empty" { dq.push_back(3) @assertion.assert_false(dq.is_empty())? } + +/// Search the deque index for a given element. +/// +/// # Example +/// ``` +/// let dq = Deque::[3, 4, 5] +/// dq.search(3) // Some(0) +/// ``` +pub fn search[T : Eq](self : Deque[T], value : T) -> Option[Int] { + for i = 0; i < self.len; i = i + 1 { + if self.buf[i] == value { + return Some(i) + } + } + None +} + +test "search" { + let dq = Deque::[3, 4, 5] + @assertion.assert_eq(dq.search(3), Some(0))? + @assertion.assert_eq(dq.search(4), Some(1))? + @assertion.assert_eq(dq.search(5), Some(2))? + @assertion.assert_eq(dq.search(6), None)? +} + +/// Checks if the vector contains an element. +/// +/// # Example +/// ``` +/// let dq = Deque::[3, 4, 5] +/// dq.contains(3) // true +/// ``` +pub fn contains[T : Eq](self : Deque[T], value : T) -> Bool { + for i = 0; i < self.len; i = i + 1 { + if self.buf[i] == value { + return true + } + } + false +} + +test "contains" { + let dq = Deque::[3, 4, 5] + @assertion.assert_true(dq.contains(3))? + @assertion.assert_true(dq.contains(4))? + @assertion.assert_true(dq.contains(5))? + @assertion.assert_false(dq.contains(6))? +}