flowchart LR
subgraph buf["buf, cap = 8 — logical order 1·2·3·4·5, head = 5, len = 5"]
direction LR
c0["0: 4"] --- c1["1: 5 ⟵ back"] --- c2["2: ·"] --- c3["3: ·"] --- c4["4: ·"] --- c5["5: 1 ⟵ head"] --- c6["6: 2"] --- c7["7: 3"]
end
c7 -. wraps to index 0 .-> c0///|
test {
let dv : @deque.Deque[Int] = Deque([])
@test.assert_eq(dv.is_empty(), true)
let dv2 = @deque.from_array([1, 2, 3, 4, 5])
@test.assert_eq(dv2.length(), 5)
let dv3 = @deque.from_iter([1, 2, 3].iter())
@test.assert_eq(dv3.length(), 3)
}///|
test {
let dv : @deque.Deque[Int] = Deque([], capacity=1024)
@test.assert_eq(dv.capacity(), 1024)
}///|
test {
let dv = @deque.from_array([1, 2, 3])
@test.assert_eq(dv.length(), 3)
@test.assert_eq(dv.is_empty(), false)
// reserve additional capacity
dv.reserve_capacity(100)
inspect(dv.capacity() >= 100, content="true")
// shrink to fit actual contents
dv.shrink_to_fit()
@test.assert_eq(dv.capacity(), 3)
}///|
test {
let dv = @deque.from_array([10, 20, 30, 40, 50])
@test.assert_eq(dv[0], 10)
@test.assert_eq(dv[4], 50)
@test.assert_eq(dv.get(2), Some(30))
@test.assert_eq(dv.get(99), None)
@test.assert_eq(dv.front(), Some(10))
@test.assert_eq(dv.back(), Some(50))
}///|
test {
let dv = @deque.from_array([2, 3])
dv.push_front(1)
dv.push_back(4)
debug_inspect(
dv,
content=(
#|<Deque: [1, 2, 3, 4]>
),
)
@test.assert_eq(dv.pop_front(), Some(1))
@test.assert_eq(dv.pop_back(), Some(4))
debug_inspect(
dv,
content=(
#|<Deque: [2, 3]>
),
)
}///|
test {
let dv = @deque.from_array([1, 2, 3])
dv[1] = 20
@test.assert_eq(dv[1], 20)
}///|
test {
let dv = @deque.from_array([1, 2, 4])
dv.insert(2, 3) // insert 3 at index 2
debug_inspect(
dv,
content=(
#|<Deque: [1, 2, 3, 4]>
),
)
let removed = dv.remove(0)
@test.assert_eq(removed, 1)
debug_inspect(
dv,
content=(
#|<Deque: [2, 3, 4]>
),
)
}///|
test {
let a = @deque.from_array([1, 2])
let b = @deque.from_array([3, 4])
debug_inspect(
a + b,
content=(
#|<Deque: [1, 2, 3, 4]>
),
)
a.append(b)
debug_inspect(
a,
content=(
#|<Deque: [1, 2, 3, 4]>
),
)
}///|
test {
let dv = @deque.from_array([1, 2, 3, 4, 5])
@test.assert_eq(dv.contains(3), true)
@test.assert_eq(dv.search(3), Some(2))
// binary_search returns Ok(index) if found, Err(insertion_point) if not
@test.assert_eq(dv.binary_search(3), Ok(2))
@test.assert_eq(dv.binary_search(6), Err(5))
// binary_search_by takes a comparison function
@test.assert_eq(dv.binary_search_by(fn(x) { x.compare(3) }), Ok(2))
}///|
test {
let dv = @deque.from_array([1, 2, 3])
// each / eachi
let buf = []
dv.each(fn(x) { buf.push(x) })
@test.assert_eq(buf, [1, 2, 3])
let pairs = []
dv.eachi(fn(i, x) { pairs.push((i, x)) })
@test.assert_eq(pairs, [(0, 1), (1, 2), (2, 3)])
// reverse iteration
let rev = []
dv.rev_each(fn(x) { rev.push(x) })
@test.assert_eq(rev, [3, 2, 1])
// iterators
debug_inspect(dv.iter().to_array(), content="[1, 2, 3]")
debug_inspect(dv.rev_iter().to_array(), content="[3, 2, 1]")
}///|
test {
let dv = @deque.from_array([1, 2, 3, 4, 5])
debug_inspect(
dv.map(fn(x) { x * 2 }),
content=(
#|<Deque: [2, 4, 6, 8, 10]>
),
)
debug_inspect(
dv.mapi(fn(i, x) { i + x }),
content=(
#|<Deque: [1, 3, 5, 7, 9]>
),
)
debug_inspect(
dv.filter(fn(x) { x % 2 == 0 }),
content=(
#|<Deque: [2, 4]>
),
)
// retain modifies in place
let dv2 = @deque.from_array([1, 2, 3, 4, 5])
dv2.retain(fn(x) { x > 3 })
debug_inspect(
dv2,
content=(
#|<Deque: [4, 5]>
),
)
// retain_map: keep Some values, drop None
let dv3 = @deque.from_array([1, 2, 3, 4])
dv3.retain_map(fn(x) { if x % 2 == 0 { Some(x * 10) } else { None } })
debug_inspect(
dv3,
content=(
#|<Deque: [20, 40]>
),
)
}///|
test {
let dv = @deque.from_array([1, 2, 3, 4, 5])
let extracted = dv.extract_if(fn(x) { x % 2 == 0 })
debug_inspect(
extracted,
content=(
#|<Deque: [2, 4]>
),
)
debug_inspect(
dv,
content=(
#|<Deque: [1, 3, 5]>
),
)
let dv2 = @deque.from_array([1, 2, 3, 4, 5])
let drained = dv2.drain(start=1, len=2)
debug_inspect(
drained,
content=(
#|<Deque: [2, 3]>
),
)
debug_inspect(
dv2,
content=(
#|<Deque: [1, 4, 5]>
),
)
}///|
test {
let dv = @deque.from_array([1, 2, 3, 4, 5])
let cs = dv.chunks(2)
debug_inspect(
cs,
content=(
#|<Deque: [<Deque: [1, 2]>, <Deque: [3, 4]>, <Deque: [5]>]>
),
)
// chunk_by groups consecutive elements that satisfy a predicate
let dv2 = @deque.from_array([1, 1, 2, 2, 3])
let grouped = dv2.chunk_by(fn(a, b) { a == b })
debug_inspect(
grouped,
content=(
#|<Deque: [<Deque: [1, 1]>, <Deque: [2, 2]>, <Deque: [3]>]>
),
)
}///|
test {
let dv = @deque.from_array([1, 2, 3])
// rev returns a new reversed deque
debug_inspect(
dv.rev(),
content=(
#|<Deque: [3, 2, 1]>
),
)
// rev_in_place reverses in place
dv.rev_in_place()
debug_inspect(
dv,
content=(
#|<Deque: [3, 2, 1]>
),
)
}///|
test {
let dv = @deque.from_array([1, 2, 3, 4, 5])
let shuffled = dv.shuffle(rand=fn(_n) { 0 }) // deterministic for test
@test.assert_eq(shuffled.length(), 5)
}///|
test {
let dv = @deque.from_array([1, 2, 3, 4, 5])
dv.truncate(3)
debug_inspect(
dv,
content=(
#|<Deque: [1, 2, 3]>
),
)
dv.clear()
@test.assert_eq(dv.is_empty(), true)
}///|
test {
let src = @deque.from_array([1, 2, 3, 4, 5])
let dst = @deque.from_array([0, 0, 0, 0, 0])
src.blit_to(dst, len=3, src_offset=1, dst_offset=2)
debug_inspect(
dst,
content=(
#|<Deque: [0, 0, 2, 3, 4]>
),
)
}///|
test {
let nested : @deque.Deque[@deque.Deque[Int]] = @deque.from_array([
@deque.from_array([1, 2]),
@deque.from_array([3, 4]),
])
debug_inspect(
nested.flatten(),
content=(
#|<Deque: [1, 2, 3, 4]>
),
)
let words = @deque.from_array(["hello", "world"])
inspect(words.join(", "), content="hello, world")
}///|
test {
let dv = @deque.from_array([1, 2, 3])
let (v1, v2) = dv.as_views()
// for a non-wrapped deque, all elements are in the first view
@test.assert_eq(v1.length() + v2.length(), 3)
}///|
test {
let dv = @deque.from_array([1, 2, 3])
@test.assert_eq(dv.to_array(), [1, 2, 3])
}///|
test {
let a = @deque.from_array([1, 2, 3])
let b = @deque.from_array([1, 2, 3])
@test.assert_eq(a == b, true)
@test.assert_eq(a.compare(@deque.from_array([1, 2, 4])) < 0, true)
}type Deque[A]Wrapped case (head + len > cap):
buf: [4, 5, _, _, _, 1, 2, 3]
^ ^
(tail) head
head = 5, len = 5, tail = (5 + 5 - 1) % 8 = 1
Logical order: [1, 2, 3, 4, 5]
Contiguous case (head + len <= cap):
buf: [_, 1, 2, 3, 4, 5, _, _]
^ ^
head (tail)
head = 1, len = 5, tail = (1 + 5 - 1) % 8 = 5
Logical order: [1, 2, 3, 4, 5]
Empty case (len == 0):
buf: [_, _, _, _]
^
head (tail is undefined, not accessed)test {
let dq1 = @deque.from_array([1, 2, 3])
let dq2 = @deque.from_array([4, 5, 6])
debug_inspect((dq1 + dq2).to_array(), content="[1, 2, 3, 4, 5, 6]")
let mut dq3 = dq2.copy()
dq3 @deque.from_array([7])
@debug.debug_inspect(dq3.to_array(), content="[4, 5, 6, 7]")
}test {
let dq1 = @deque.from_array([1, 2, 3])
let dq2 = @deque.from_array([1, 2, 4])
let dq3 = @deque.from_array([1, 2])
inspect(dq1.compare(dq2), content="-1") // dq1 < dq2
inspect(dq2.compare(dq1), content="1") // dq2 > dq1
inspect(dq1.compare(dq3), content="1") // dq1 > dq3 (longer)
inspect(dq1.compare(dq1), content="0") // dq1 = dq1
}test {
let dq1 = @deque.from_array([1, 2, 3])
let dq2 = @deque.from_array([1, 2, 3])
let dq3 = @deque.from_array([3, 2, 1])
inspect(dq1 == dq2, content="true")
inspect(dq1 == dq3, content="false")
}test {
let dq1 = @deque.from_array([1, 2, 3])
let dq2 = @deque.from_array([1, 2, 3])
let dq3 = @deque.from_array([1, 2, 3, 4])
@test.assert_eq(Hash::hash(dq1), Hash::hash(dq2)) // same elements → same hash
@test.assert_not_eq(Hash::hash(dq1), Hash::hash(dq3)) // different elements → different hash
}test {
let dq = @deque.from_array([1, 2, 3])
let json = @json.to_json(dq)
@debug.debug_inspect(json, content="Array([Number(1), Number(2), Number(3)])")
}test {
let json = @json.parse("[1, 2, 3]")
let dq : @deque.Deque[Int] = @json.from_json(json)
@debug.debug_inspect(
dq,
content=(
#|<Deque: [1, 2, 3]>
),
)
}test {
let arr : ReadOnlyArray[Int] = [1, 2, 3, 4, 5]
let dq = @deque.Deque(arr)
@debug.debug_inspect(
dq,
content=(
#|<Deque: [1, 2, 3, 4, 5]>
),
)
}test {
let v1 = @deque.from_array([1, 2, 3])
let v2 = @deque.from_array([4, 5, 6])
v1.append(v2)
debug_inspect(
v1,
content=(
#|<Deque: [1, 2, 3, 4, 5, 6]>
),
)
let v1 = @deque.from_array([1, 2, 3])
let v2 = @deque.from_array([])
v1.append(v2)
@debug.debug_inspect(
v1,
content=(
#|<Deque: [1, 2, 3]>
),
)
}test {
let dq = @deque.from_array([1, 2, 3, 4, 5])
let (v1, v2) = dq.as_views()
inspect(v1.length(), content="5")
inspect(v2.length(), content="0")
}test {
let dv = @deque.from_array([1, 2, 3, 4, 5])
inspect(dv[2], content="3")
}test {
let dv = @deque.from_array([1, 2, 3, 4, 5])
@test.assert_eq(dv.back(), Some(5))
}test {
let dq = @deque.from_array([1, 3, 5, 7, 9])
let result = dq.binary_search(5)
@debug.debug_inspect(result, content="Ok(2)")
}test {
let dq = @deque.from_array([1, 3, 5, 7, 9])
let find_3 = dq.binary_search_by(x => x.compare(3))
debug_inspect(find_3, content="Ok(1)")
let find_4 = dq.binary_search_by(x => x.compare(4))
@debug.debug_inspect(find_4, content="Err(2)")
}test {
let d1 = @deque.from_array([1, 2, 3, 4, 5])
let d2 = @deque.from_array([0, 0])
d1.blit_to(d2, len=3, dst_offset=1)
@debug.debug_inspect(d2.to_array(), content="[0, 1, 2, 3]")
}test {
let dq = @deque.Deque([], capacity=10)
dq.push_back(1)
dq.push_back(2)
inspect(dq.capacity(), content="10")
}test {
let d = @deque.from_array([1, 1, 2, 3, 2, 3, 2, 3, 4])
let chunks = d.chunk_by((x, y) => x <= y)
@debug.debug_inspect(
chunks.to_array().map(c => c.to_array()),
content="[[1, 1, 2, 3], [2, 3], [2, 3, 4]]",
)
let empty : @deque.Deque[Int] = @deque.from_array([])
@debug.debug_inspect(
empty.chunk_by((x, y) => x <= y).to_array(),
content="[]",
)
}test {
let d = @deque.from_array([1, 2, 3, 4, 5])
let chunks = d.chunks(2)
@debug.debug_inspect(
chunks.to_array().map(c => c.to_array()),
content="[[1, 2], [3, 4], [5]]",
)
let d : @deque.Deque[Int] = @deque.from_array([])
inspect(d.chunks(3).length(), content="0")
}test {
let dv = @deque.from_array([1, 2, 3, 4, 5])
dv.clear()
inspect(dv.length(), content="0")
}test {
let dq = @deque.from_array([1, 2, 3, 4, 5])
inspect(dq.contains(3), content="true")
inspect(dq.contains(6), content="false")
}test {
let dq = @deque.from_array([1, 2, 3, 4, 5])
let copied = dq.copy()
@debug.debug_inspect(
copied,
content=(
#|<Deque: [1, 2, 3, 4, 5]>
),
)
}test {
let deque = @deque.from_array([1, 2, 3, 4, 5, 6, 7, 8, 9])
let deque_test = deque.drain(start=2, len=4)
debug_inspect(
deque_test,
content=(
#|<Deque: [3, 4, 5, 6]>
),
)
@debug.debug_inspect(
deque,
content=(
#|<Deque: [1, 2, 7, 8, 9]>
),
)
}test {
let dv = @deque.from_array([1, 2, 3, 4, 5])
let mut sum = 0
dv.each(x => sum x)
inspect(sum, content="15")
}test {
let dv = @deque.from_array([1, 2, 3, 4, 5])
let mut idx_sum = 0
dv.eachi((i, _x) => idx_sum i)
inspect(idx_sum, content="10")
}test {
let d = @deque.from_array([1, 2, 3, 4, 5])
let extracted = d.extract_if(x => x % 2 == 0)
debug_inspect(extracted.to_array(), content="[2, 4]")
@debug.debug_inspect(d.to_array(), content="[1, 3, 5]")
}test {
let dq = @deque.from_array([1, 2, 3, 4, 5])
let evens = dq.filter(x => x % 2 == 0)
@debug.debug_inspect(
evens,
content=(
#|<Deque: [2, 4]>
),
)
}test {
let deque = @deque.from_array([
@deque.from_array([1, 2, 3]),
@deque.from_array([4, 5, 6]),
@deque.from_array([7, 8]),
])
let deque_test = deque.flatten()
@debug.debug_inspect(
deque_test,
content=(
#|<Deque: [1, 2, 3, 4, 5, 6, 7, 8]>
),
)
}test {
let arr = [1, 2, 3, 4, 5]
let dq = @deque.from_iter(arr.iter())
@debug.debug_inspect(
dq,
content=(
#|<Deque: [1, 2, 3, 4, 5]>
),
)
}test {
let dv = @deque.from_array([1, 2, 3, 4, 5])
@test.assert_eq(dv.front(), Some(1))
}test {
let v1 = @deque.from_array([1, 2, 3])
v1.insert(0, 0) // insert at the front
debug_inspect(
v1,
content=(
#|<Deque: [0, 1, 2, 3]>
),
)
let v2 = @deque.from_array([1, 2, 4])
v2.insert(2, 3) // insert in the middle
debug_inspect(
v2,
content=(
#|<Deque: [1, 2, 3, 4]>
),
)
let v3 = @deque.from_array([2, 3, 4])
v3.insert(3, 5) // insert at the end
@debug.debug_inspect(
v3,
content=(
#|<Deque: [2, 3, 4, 5]>
),
)
}test {
let dv = @deque.Deque([])
inspect(dv.is_empty(), content="true")
dv.push_back(1)
inspect(dv.is_empty(), content="false")
}test {
let dq = @deque.from_array([1, 2, 3, 4, 5])
let mut sum = 0
dq.iter().each(x => sum x)
inspect(sum, content="15")
}test {
let dq = @deque.from_array([10, 20, 30])
let mut sum = 0
let it = dq.iter2()
while it.next() is Some((i, x)) {
sum i * x
}
inspect(sum, content="80") // 0*10 + 1*20 + 2*30 = 80
}test {
let deque = @deque.from_array(["a", "b", "c"])
let s1 = deque.join("")
inspect(s1, content="abc")
let s2 = deque.join(",")
inspect(s2, content="a,b,c")
}test {
let dq = @deque.from_array([1, 2, 3])
inspect(dq.length(), content="3")
dq.push_back(4)
inspect(dq.length(), content="4")
}test {
let dv = @deque.from_array([3, 4, 5])
let dv2 = dv.map(x => x + 1)
@test.assert_eq(dv2, @deque.from_array([4, 5, 6]))
}test {
let dv = @deque.from_array([3, 4, 5])
let dv2 = dv.mapi((i, x) => x + i) // @deque.from_array([3, 5, 7])
@test.assert_eq(dv2, @deque.from_array([3, 5, 7]))
}test {
let dv = @deque.from_array([1, 2, 3, 4, 5])
@test.assert_eq(dv.pop_back(), Some(5))
}test {
let dv = @deque.from_array([1, 2, 3, 4, 5])
@test.assert_eq(dv.pop_front(), Some(1))
}test {
let dv = @deque.from_array([1, 2, 3, 4, 5])
dv.push_back(6)
@test.assert_eq(dv.back(), Some(6))
}test {
let dv = @deque.from_array([1, 2, 3, 4, 5])
dv.push_front(0)
@test.assert_eq(dv.front(), Some(0))
}test {
let v1 = @deque.from_array([0, 1, 2, 3])
let x = v1.remove(0) // remove from the front
debug_inspect(
(x, v1),
content=(
#|(0, <Deque: [1, 2, 3]>)
),
)
let v2 = @deque.from_array([1, 2, 3, 4])
let y = v2.remove(2) // remove from the middle
debug_inspect(
(y, v2),
content=(
#|(3, <Deque: [1, 2, 4]>)
),
)
let v3 = @deque.from_array([2, 3, 4, 5])
let z = v3.remove(3) // remove from the end
@debug.debug_inspect(
(z, v3),
content=(
#|(5, <Deque: [2, 3, 4]>)
),
)
}test {
let dv = @deque.from_array([1])
dv.reserve_capacity(10)
inspect(dv.capacity(), content="10")
}test {
let dq = @deque.from_array([1, 2, 3, 4, 5])
dq.retain(x => x % 2 == 0)
@debug.debug_inspect(
dq,
content=(
#|<Deque: [2, 4]>
),
)
}test {
let dq = @deque.from_array([1, 2, 3, 4, 5])
dq.retain_map(x => if x % 2 == 0 { Some(x * 2) } else { None })
@debug.debug_inspect(
dq,
content=(
#|<Deque: [4, 8]>
),
)
}test {
let dq = @deque.from_array([1, 2, 3, 4, 5])
debug_inspect(
dq.rev(),
content=(
#|<Deque: [5, 4, 3, 2, 1]>
),
)
@debug.debug_inspect(
dq,
content=(
#|<Deque: [1, 2, 3, 4, 5]>
),
) // original deque unchanged
}test {
let dv = @deque.from_array([1, 2, 3, 4, 5])
let mut sum = 0
dv.rev_each(x => sum x)
inspect(sum, content="15")
}test {
let dv = @deque.from_array([1, 2, 3, 4, 5])
let mut idx_sum = 0
dv.rev_eachi((i, _x) => idx_sum i)
inspect(idx_sum, content="10")
}test {
let dq = @deque.from_array([1, 2, 3, 4, 5])
dq.rev_in_place()
debug_inspect(
dq,
content=(
#|<Deque: [5, 4, 3, 2, 1]>
),
)
let dq : @deque.Deque[Int] = Deque([])
dq.rev_in_place()
@debug.debug_inspect(
dq,
content=(
#|<Deque: []>
),
)
}test {
let dq = @deque.from_array([1, 2, 3])
let mut sum = 0
dq.rev_iter().each(x => sum = sum * 10 + x)
inspect(sum, content="321")
}test {
let dq = @deque.from_array([1, 2, 3])
let mut s = ""
let it = dq.rev_iter2()
while it.next() is Some((i, x)) {
s "\{i}:\{x} "
}
inspect(s, content="0:3 1:2 2:1 ")
}test {
let dq = @deque.from_array([1, 2, 3, 2, 1])
@debug.debug_inspect(dq.search(2), content="Some(1)")
@debug.debug_inspect(dq.search(4), content="None")
}test {
let dv = @deque.from_array([1, 2, 3, 4, 5])
dv[2] = 1
inspect(dv[2], content="1")
}test {
let dv = @deque.Deque([], capacity=10)
dv.push_back(1)
dv.push_back(2)
dv.push_back(3)
inspect(dv.capacity(), content="10")
dv.shrink_to_fit()
inspect(dv.capacity(), content="3")
}test {
let dq = @deque.from_array([1, 2, 3, 4, 5])
let arr = dq.to_array()
@debug.debug_inspect(arr, content="[1, 2, 3, 4, 5]")
}test {
let dq = @deque.from_array([1, 2, 3, 4, 5])
dq.truncate(3)
@debug.debug_inspect(
dq,
content=(
#|<Deque: [1, 2, 3]>
),
)
}Install
Installed by default