Skip to content

Commit

Permalink
feat(deque): add @deque.rev_iter[2]()
Browse files Browse the repository at this point in the history
  • Loading branch information
rami3l committed Dec 26, 2024
1 parent 921e2f7 commit 703858a
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 2 deletions.
53 changes: 53 additions & 0 deletions deque/deque.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,59 @@ pub fn iter2[A](self : T[A]) -> Iter2[Int, A] {
})
}

///|
pub fn rev_iter[A](self : T[A]) -> Iter[A] {
Iter::new(fn(yield_) {
guard not(self.is_empty()) else { IterContinue }
let { head, buf, len, .. } = self
let cap = buf.length()
let head_len = cap - head
if head_len >= len {
for i = head + len - 1; i >= head; i = i - 1 {
guard let IterContinue = yield_(buf[i]) else { x => return x }

}
} else {
for i = len - head_len - 1; i >= 0; i = i - 1 {
guard let IterContinue = yield_(buf[i]) else { x => return x }

}
for i = cap - 1; i >= head; i = i - 1 {
guard let IterContinue = yield_(buf[i]) else { x => return x }

}
}
IterContinue
})
}

///|
pub fn rev_iter2[A](self : T[A]) -> Iter2[Int, A] {
Iter2::new(fn(yield_) {
guard not(self.is_empty()) else { IterContinue }
let { head, buf, len, .. } = self
let cap = buf.length()
let head_len = cap - head
let mut j = 0
if head_len >= len {
for i = head + len - 1; i >= head; i = i - 1 {
guard let IterContinue = yield_(j, buf[i]) else { x => return x }
j += 1
}
} else {
for i = len - head_len - 1; i >= 0; i = i - 1 {
guard let IterContinue = yield_(j, buf[i]) else { x => return x }
j += 1
}
for i = cap - 1; i >= head; i = i - 1 {
guard let IterContinue = yield_(j, buf[i]) else { x => return x }
j += 1
}
}
IterContinue
})
}

///|
pub fn T::from_iter[A](iter : Iter[A]) -> T[A] {
let dq = T::new()
Expand Down
2 changes: 2 additions & 0 deletions deque/deque.mbti
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ impl T {
reserve_capacity[A](Self[A], Int) -> Unit
rev_each[A](Self[A], (A) -> Unit) -> Unit
rev_eachi[A](Self[A], (Int, A) -> Unit) -> Unit
rev_iter[A](Self[A]) -> Iter[A]
rev_iter2[A](Self[A]) -> Iter2[Int, A]
search[A : Eq](Self[A], A) -> Int?
shrink_to_fit[A](Self[A]) -> Unit
unsafe_pop_back[A](Self[A]) -> Unit
Expand Down
31 changes: 29 additions & 2 deletions deque/deque_test.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ test "mapi" {
inspect!(dve.mapi(fn(_idx, x) { x }), content="@deque.of([])")
}

test "iter_rev" {
test "rev_each" {
let mut i = 6
let mut failed = false
@deque.of([1, 2, 3, 4, 5]).rev_each(fn(elem) {
Expand All @@ -141,7 +141,7 @@ test "iter_rev" {
assert_false!(failed)
}

test "iter_revi" {
test "rev_eachi" {
let mut i = 6
let mut j = 0
let mut failed = false
Expand Down Expand Up @@ -447,6 +447,33 @@ test "iter2 when tail needs to wrap around" {
inspect!(dq.iter2().to_array(), content="[(0, 2), (1, 3)]")
}

test "rev_iter when head needs to wrap around" {
let dq = @deque.new(capacity=4)
dq.push_back(1)
dq.unsafe_pop_front()
dq.push_back(2)
dq.unsafe_pop_front()
for i in 3..=6 {
dq.push_back(i)
}
inspect!(dq.rev_iter().to_array(), content="[6, 5, 4, 3]")
}

test "rev_iter2 when head needs to wrap around" {
let dq = @deque.new(capacity=4)
dq.push_back(1)
dq.unsafe_pop_front()
dq.push_back(2)
dq.unsafe_pop_front()
for i in 3..=6 {
dq.push_back(i)
}
inspect!(
dq.rev_iter2().to_array(),
content="[(0, 6), (1, 5), (2, 4), (3, 3)]",
)
}

test "deque push_front when empty" {
let d = @deque.of([0, 1])
ignore(d.pop_back())
Expand Down

0 comments on commit 703858a

Please sign in to comment.