Skip to content

Commit

Permalink
Merge pull request moonbitlang#438 from ZnPdCo/as-iter
Browse files Browse the repository at this point in the history
add as_iter and to_array method
  • Loading branch information
bobzhang authored May 26, 2024
2 parents 6326ab0 + 1df994f commit d4cb07e
Show file tree
Hide file tree
Showing 10 changed files with 216 additions and 11 deletions.
61 changes: 50 additions & 11 deletions immut/array/immutable_vec.mbt → immut/array/array.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,23 @@ pub fn ImmutableVec::empty[T]() -> ImmutableVec[T] {
{ tree: Tree::empty(), size: 0, shift: 0 }
}

test "is_empty" {
let v = ImmutableVec::[1, 2, 3, 4, 5]
let ve : ImmutableVec[Int] = ImmutableVec::empty()
inspect(is_empty(v), content="false")?
inspect(is_empty(ve), content="true")?
}

pub fn to_string[T : Show](self : ImmutableVec[T]) -> String {
let mut s = "ImmutableVec::[".to_string()
for i = 0; i < self.size; i = i + 1 {
s = s + self[i].to_string()
if i < self.size - 1 {
s = s + ", "
}
}
self.iteri(
fn(i, v) {
s = s + v.to_string()
if i < self.size - 1 {
s = s + ", "
}
},
)
s = s + "]"
s
}
Expand All @@ -39,11 +48,41 @@ pub fn is_empty[T](v : ImmutableVec[T]) -> Bool {
v.size == 0
}

test "is_empty" {
let v = ImmutableVec::[1, 2, 3, 4, 5]
let ve : ImmutableVec[Int] = ImmutableVec::empty()
inspect(is_empty(v), content="false")?
inspect(is_empty(ve), content="true")?
pub fn to_array[T](self : ImmutableVec[T]) -> Array[T] {
let arr = []
self.iter(fn(v) { arr.push(v) })
arr
}

test "to_array" {
let v = ImmutableVec::[1, 2, 3, 4]
inspect(v.to_array().to_string(), content="[1, 2, 3, 4]")?
inspect(v.push(5).to_array().to_string(), content="[1, 2, 3, 4, 5]")?
}

pub fn as_iter[T](self : ImmutableVec[T]) -> @iter.Iter[T] {
@iter.Iter::_unstable_internal_make(
fn(yield) {
let arr = self.to_array()
for i = 0; i < self.size; i = i + 1 {
if yield(arr[i]).not() {
break false
}
} else {
true
}
},
)
}

test "as_iter" {
let buf = Buffer::make(20)
let v = ImmutableVec::[1, 2, 3]
v.as_iter().iter(fn(e) { buf.write_string("[\(e)]") })
inspect(buf, content="[1][2][3]")?
buf.reset()
v.as_iter().take(2).iter(fn(e) { buf.write_string("[\(e)]") })
inspect(buf, content="[1][2]")?
}

pub fn length[T](v : ImmutableVec[T]) -> Int {
Expand Down
4 changes: 4 additions & 0 deletions immut/array/array.mbti
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package moonbitlang/core/immut/array

alias @moonbitlang/core/iter as @iter

// Values
fn immutable_push[T](Array[T], T) -> Array[T]

Expand All @@ -12,6 +14,7 @@ fn length[T](ImmutableVec[T]) -> Int
// Types and methods
type ImmutableVec
impl ImmutableVec {
as_iter[T](Self[T]) -> @iter.Iter[T]
copy[T](Self[T]) -> Self[T]
debug_write[T : Debug](Self[T], Buffer) -> Unit
empty[T]() -> Self[T]
Expand All @@ -27,6 +30,7 @@ impl ImmutableVec {
op_get[T](Self[T], Int) -> T
push[T](Self[T], T) -> Self[T]
set[T](Self[T], Int, T) -> Self[T]
to_array[T](Self[T]) -> Array[T]
to_string[T : Show](Self[T]) -> String
}

Expand Down
1 change: 1 addition & 0 deletions immut/array/moon.pkg.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"moonbitlang/core/fixedarray",
"moonbitlang/core/coverage",
"moonbitlang/core/array",
"moonbitlang/core/iter",
"moonbitlang/core/assertion"
]
}
2 changes: 2 additions & 0 deletions immut/priority_queue/moon.pkg.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{
"import": [
"moonbitlang/core/builtin",
"moonbitlang/core/iter",
"moonbitlang/core/array",
"moonbitlang/core/assertion",
"moonbitlang/core/coverage"
]
Expand Down
54 changes: 54 additions & 0 deletions immut/priority_queue/priority_queue.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,60 @@ test "from_array" {
inspect(queue.peek(), content="Some(5)")?
}

pub fn to_array[T : Compare](self : ImmutablePriorityQueue[T]) -> Array[T] {
let arr : Array[T] = []
fn go(x : Cont[T]) {
match x {
Node(v, child) => {
arr.push(v)
loop child {
Nil => ()
Cons(x, xs) => {
go(x)
continue xs
}
}
}
Empty => ()
}
}

go(self.body)
arr.sort_by(fn(x, y) { if x < y { 1 } else { -1 } })
arr
}

test "to_array" {
let v = ImmutablePriorityQueue::[1, 2, 3, 4]
inspect(v.to_array().to_string(), content="[4, 3, 2, 1]")?
inspect(v.push(0).to_array().to_string(), content="[4, 3, 2, 1, 0]")?
}

pub fn as_iter[T : Compare](self : ImmutablePriorityQueue[T]) -> @iter.Iter[T] {
@iter.Iter::_unstable_internal_make(
fn(yield) {
let arr = self.to_array()
for i = 0; i < arr.length(); i = i + 1 {
if yield(arr[i]).not() {
break false
}
} else {
true
}
},
)
}

test "as_iter" {
let buf = Buffer::make(20)
let v = ImmutablePriorityQueue::[1, 2, 3]
v.as_iter().iter(fn(e) { buf.write_string("[\(e)]") })
inspect(buf, content="[3][2][1]")?
buf.reset()
v.as_iter().take(2).iter(fn(e) { buf.write_string("[\(e)]") })
inspect(buf, content="[3][2]")?
}

fn meld[T : Compare](l : Cont[T], r : Cont[T]) -> Cont[T] {
match (l, r) {
(Empty, _) => r
Expand Down
4 changes: 4 additions & 0 deletions immut/priority_queue/priority_queue.mbti
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package moonbitlang/core/immut/priority_queue

alias @moonbitlang/core/iter as @iter

// Values

// Types and methods
type ImmutablePriorityQueue
impl ImmutablePriorityQueue {
as_iter[T : Compare + Eq](Self[T]) -> @iter.Iter[T]
from_array[T : Compare + Eq](Array[T]) -> Self[T]
is_empty[T](Self[T]) -> Bool
length[T](Self[T]) -> Int
Expand All @@ -13,6 +16,7 @@ impl ImmutablePriorityQueue {
pop[T : Compare + Eq](Self[T]) -> Option[Self[T]]
pop_exn[T : Compare + Eq](Self[T]) -> Self[T]
push[T : Compare + Eq](Self[T], T) -> Self[T]
to_array[T : Compare + Eq](Self[T]) -> Array[T]
}

// Traits
Expand Down
9 changes: 9 additions & 0 deletions priority_queue/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,12 @@ let pq = PriorityQueue::[1, 2, 3, 4, 5]
pq.clear()
pq.is_empty() // true
```

### Copy and Transfer

You can copy a priority queue using the `copy` method.

```moonbit
let pq = PriorityQueue::[1, 2, 3]
let pq2 = pq.copy()
```
2 changes: 2 additions & 0 deletions priority_queue/moon.pkg.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{
"import": [
"moonbitlang/core/builtin",
"moonbitlang/core/iter",
"moonbitlang/core/array",
"moonbitlang/core/assertion",
"moonbitlang/core/coverage"
]
Expand Down
85 changes: 85 additions & 0 deletions priority_queue/priority_queue.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,91 @@ test "from_array" {
@assertion.assert_eq(pq.peek(), Some(5))?
}

fn copy_node[T](x : Node[T]) -> Node[T] {
match x {
Nil => Nil
Cons(top) =>
Cons(
{
content: top.content,
sibling: copy_node(top.sibling),
child: copy_node(top.child),
},
)
}
}

/// Return a copy of the queue.
///
/// # Example
/// ```
/// let queue : PriorityQueue[Int] = PriorityQueue::[1, 2, 3, 4]
/// let queue2 : PriorityQueue[Int] = PriorityQueue.copy()
/// ```
pub fn copy[T](self : PriorityQueue[T]) -> PriorityQueue[T] {
let new_que : PriorityQueue[T] = { len: self.len, top: copy_node(self.top) }
new_que
}

test "copy" {
let v = PriorityQueue::[1, 2, 3, 4]
let ve = v.copy()
inspect(v.peek().to_string(), content="Some(4)")?
inspect(ve.peek().to_string(), content="Some(4)")?
v.pop() |> ignore
inspect(v.peek().to_string(), content="Some(3)")?
inspect(ve.peek().to_string(), content="Some(4)")?
}

pub fn to_array[T : Compare](self : PriorityQueue[T]) -> Array[T] {
let arr : Array[T] = []
fn go(x : Node[T]) {
match x {
Cons(node) => {
arr.push(node.content)
go(node.sibling)
go(node.child)
}
Nil => ()
}
}

go(self.top)
arr.sort_by(fn(x, y) { if x < y { 1 } else { -1 } })
arr
}

test "to_array" {
let v = PriorityQueue::[1, 2, 3, 4]
inspect(v.to_array().to_string(), content="[4, 3, 2, 1]")?
inspect(v.to_array().to_string(), content="[4, 3, 2, 1]")?
}

pub fn as_iter[T : Compare](self : PriorityQueue[T]) -> @iter.Iter[T] {
@iter.Iter::_unstable_internal_make(
fn(yield) {
let arr = self.to_array()
for i = 0; i < arr.length(); i = i + 1 {
if yield(arr[i]).not() {
break false
}
} else {
true
}
},
)
}

test "as_iter" {
let buf = Buffer::make(20)
let v = PriorityQueue::[1, 2, 3]
v.as_iter().iter(fn(e) { buf.write_string("[\(e)]") })
inspect(buf, content="[3][2][1]")?
buf.reset()
v.as_iter().take(2).iter(fn(e) { buf.write_string("[\(e)]") })
inspect(buf, content="[3][2]")?
}

fn meld[T : Compare](x : Node[T], y : Node[T]) -> Node[T] {
match (x, y) {
(Nil, _) => y
Expand Down
5 changes: 5 additions & 0 deletions priority_queue/priority_queue.mbti
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package moonbitlang/core/priority_queue

alias @moonbitlang/core/iter as @iter

// Values

// Types and methods
type PriorityQueue
impl PriorityQueue {
as_iter[T : Compare + Eq](Self[T]) -> @iter.Iter[T]
clear[T](Self[T]) -> Unit
copy[T](Self[T]) -> Self[T]
from_array[T : Compare + Eq](Array[T]) -> Self[T]
is_empty[T](Self[T]) -> Bool
length[T](Self[T]) -> Int
Expand All @@ -14,6 +18,7 @@ impl PriorityQueue {
pop[T : Compare + Eq](Self[T]) -> Option[T]
pop_exn[T : Compare + Eq](Self[T]) -> Unit
push[T : Compare + Eq](Self[T], T) -> Unit
to_array[T : Compare + Eq](Self[T]) -> Array[T]
}

// Traits
Expand Down

0 comments on commit d4cb07e

Please sign in to comment.