diff --git a/src/Blob.mo b/src/Blob.mo
index e9318e72c..a78baeca0 100644
--- a/src/Blob.mo
+++ b/src/Blob.mo
@@ -133,7 +133,7 @@ module {
/// let result = Blob.compare(blob1, blob2);
/// assert result == #less;
/// ```
- public func compare(b1 : Blob, b2 : Blob) : Order.Order {
+ public persistent func compare(b1 : Blob, b2 : Blob) : Order.Order {
let c = Prim.blobCompare(b1, b2);
if (c < 0) #less else if (c == 0) #equal else #greater
};
diff --git a/src/Bool.mo b/src/Bool.mo
index 45b0cee78..d8e8cf2f0 100644
--- a/src/Bool.mo
+++ b/src/Bool.mo
@@ -88,7 +88,7 @@ module {
/// assert Bool.compare(true, true) == #equal;
/// assert Bool.compare(false, true) == #less;
/// ```
- public func compare(a : Bool, b : Bool) : Order.Order {
+ public persistent func compare(a : Bool, b : Bool) : Order.Order {
if (a == b) #equal else if a #greater else #less
};
diff --git a/src/Char.mo b/src/Char.mo
index c81ed9f91..15bc20e5e 100644
--- a/src/Char.mo
+++ b/src/Char.mo
@@ -207,7 +207,7 @@ module {
/// assert Char.compare('B', 'A') == #greater;
/// assert Char.compare('A', 'A') == #equal;
/// ```
- public func compare(a : Char, b : Char) : { #less; #equal; #greater } {
+ public persistent func compare(a : Char, b : Char) : { #less; #equal; #greater } {
if (a < b) { #less } else if (a == b) { #equal } else { #greater }
};
diff --git a/src/Float.mo b/src/Float.mo
index 7d79489d5..7af5d44f7 100644
--- a/src/Float.mo
+++ b/src/Float.mo
@@ -73,7 +73,7 @@ module {
/// ```motoko include=import
/// assert Float.isNaN(0.0/0.0);
/// ```
- public func isNaN(number : Float) : Bool {
+ public persistent func isNaN(number : Float) : Bool {
number != number
};
@@ -194,7 +194,9 @@ module {
/// let epsilon = 1e-6;
/// assert Float.equal(Float.copySign(1.2, -2.3), -1.2, epsilon);
/// ```
- public let copySign : (x : Float, y : Float) -> Float = Prim.floatCopySign;
+ public persistent func copySign(x : Float, y : Float): Float {
+ Prim.floatCopySign(x, y)
+ };
/// Returns the smaller value of `x` and `y`.
///
@@ -608,7 +610,7 @@ module {
/// ```motoko include=import
/// assert Float.compare(0.123, 0.1234) == #less;
/// ```
- public func compare(x : Float, y : Float) : Order.Order {
+ public persistent func compare(x : Float, y : Float) : Order.Order {
if (isNaN(x)) {
if (isNegative(x)) {
if (isNaN(y) and isNegative(y)) { #equal } else { #less }
@@ -626,7 +628,7 @@ module {
}
};
- func isNegative(number : Float) : Bool {
+ persistent func isNegative(number : Float) : Bool {
copySign(1.0, number) < 0.0
};
diff --git a/src/Int.mo b/src/Int.mo
index e0aabb60c..c9d2f9252 100644
--- a/src/Int.mo
+++ b/src/Int.mo
@@ -259,7 +259,7 @@ module {
/// import Array "mo:core/Array";
/// assert Array.sort([1, -2, -3], Int.compare) == [-3, -2, 1];
/// ```
- public func compare(x : Int, y : Int) : Order.Order {
+ public persistent func compare(x : Int, y : Int) : Order.Order {
if (x < y) { #less } else if (x == y) { #equal } else { #greater }
};
diff --git a/src/Int16.mo b/src/Int16.mo
index b423a56c5..d5453e26e 100644
--- a/src/Int16.mo
+++ b/src/Int16.mo
@@ -256,7 +256,7 @@ module {
/// import Array "mo:core/Array";
/// assert Array.sort([1, -2, -3] : [Int16], Int16.compare) == [-3, -2, 1];
/// ```
- public func compare(x : Int16, y : Int16) : Order.Order {
+ public persistent func compare(x : Int16, y : Int16) : Order.Order {
if (x < y) { #less } else if (x == y) { #equal } else { #greater }
};
diff --git a/src/Int32.mo b/src/Int32.mo
index c9a4a122d..e6bfafc4e 100644
--- a/src/Int32.mo
+++ b/src/Int32.mo
@@ -265,7 +265,7 @@ module {
/// import Array "mo:core/Array";
/// assert Array.sort([1, -2, -3] : [Int32], Int32.compare) == [-3, -2, 1];
/// ```
- public func compare(x : Int32, y : Int32) : Order.Order {
+ public persistent func compare(x : Int32, y : Int32) : Order.Order {
if (x < y) { #less } else if (x == y) { #equal } else { #greater }
};
diff --git a/src/Int64.mo b/src/Int64.mo
index 9744fba9f..813344ea5 100644
--- a/src/Int64.mo
+++ b/src/Int64.mo
@@ -251,7 +251,7 @@ module {
/// import Array "mo:core/Array";
/// assert Array.sort([1, -2, -3] : [Int64], Int64.compare) == [-3, -2, 1];
/// ```
- public func compare(x : Int64, y : Int64) : Order.Order {
+ public persistent func compare(x : Int64, y : Int64) : Order.Order {
if (x < y) { #less } else if (x == y) { #equal } else { #greater }
};
diff --git a/src/Int8.mo b/src/Int8.mo
index 70519972f..81e805dd9 100644
--- a/src/Int8.mo
+++ b/src/Int8.mo
@@ -246,7 +246,7 @@ module {
/// import Array "mo:core/Array";
/// assert Array.sort([1, -2, -3] : [Int8], Int8.compare) == [-3, -2, 1];
/// ```
- public func compare(x : Int8, y : Int8) : Order.Order {
+ public persistent func compare(x : Int8, y : Int8) : Order.Order {
if (x < y) { #less } else if (x == y) { #equal } else { #greater }
};
diff --git a/src/Nat.mo b/src/Nat.mo
index 560aba056..9ea084037 100644
--- a/src/Nat.mo
+++ b/src/Nat.mo
@@ -210,7 +210,7 @@ module {
/// import Array "mo:core/Array";
/// assert Array.sort([2, 3, 1], Nat.compare) == [1, 2, 3];
/// ```
- public func compare(x : Nat, y : Nat) : Order.Order {
+ public persistent func compare(x : Nat, y : Nat) : Order.Order {
if (x < y) { #less } else if (x == y) { #equal } else { #greater }
};
diff --git a/src/Nat16.mo b/src/Nat16.mo
index ecd8b600f..fe177ed1d 100644
--- a/src/Nat16.mo
+++ b/src/Nat16.mo
@@ -239,7 +239,7 @@ module {
/// import Array "mo:core/Array";
/// assert Array.sort([2, 3, 1] : [Nat16], Nat16.compare) == [1, 2, 3];
/// ```
- public func compare(x : Nat16, y : Nat16) : Order.Order {
+ public persistent func compare(x : Nat16, y : Nat16) : Order.Order {
if (x < y) { #less } else if (x == y) { #equal } else { #greater }
};
diff --git a/src/Nat32.mo b/src/Nat32.mo
index 05bac731b..a9997e839 100644
--- a/src/Nat32.mo
+++ b/src/Nat32.mo
@@ -239,7 +239,7 @@ module {
/// import Array "mo:core/Array";
/// assert Array.sort([2, 3, 1] : [Nat32], Nat32.compare) == [1, 2, 3];
/// ```
- public func compare(x : Nat32, y : Nat32) : Order.Order {
+ public persistent func compare(x : Nat32, y : Nat32) : Order.Order {
if (x < y) { #less } else if (x == y) { #equal } else { #greater }
};
diff --git a/src/Nat64.mo b/src/Nat64.mo
index 3539b2743..42e596747 100644
--- a/src/Nat64.mo
+++ b/src/Nat64.mo
@@ -217,7 +217,7 @@ module {
/// import Array "mo:core/Array";
/// assert Array.sort([2, 3, 1] : [Nat64], Nat64.compare) == [1, 2, 3];
/// ```
- public func compare(x : Nat64, y : Nat64) : Order.Order {
+ public persistent func compare(x : Nat64, y : Nat64) : Order.Order {
if (x < y) { #less } else if (x == y) { #equal } else { #greater }
};
diff --git a/src/Nat8.mo b/src/Nat8.mo
index bb0dc4f83..e9a2a49d4 100644
--- a/src/Nat8.mo
+++ b/src/Nat8.mo
@@ -212,7 +212,7 @@ module {
/// import Array "mo:core/Array";
/// assert Array.sort([2, 3, 1] : [Nat8], Nat8.compare) == [1, 2, 3];
/// ```
- public func compare(x : Nat8, y : Nat8) : Order.Order {
+ public persistent func compare(x : Nat8, y : Nat8) : Order.Order {
if (x < y) { #less } else if (x == y) { #equal } else { #greater }
};
diff --git a/src/Option.mo b/src/Option.mo
index def91a027..9f7f8a92a 100644
--- a/src/Option.mo
+++ b/src/Option.mo
@@ -130,7 +130,7 @@ module {
/// - `#less` if the first value is `null` and the second is not,
/// - `#greater` if the first value is not `null` and the second is,
/// - the result of the comparison function when both values are not `null`.
- public func compare(x : ?A, y : ?A, cmp : (A, A) -> Types.Order) : Types.Order = switch (x, y) {
+ public persistent func compare(x : ?A, y : ?A, cmp : (A, A) -> Types.Order) : Types.Order = switch (x, y) {
case (null, null) #equal;
case (null, _) #less;
case (_, null) #greater;
diff --git a/src/Principal.mo b/src/Principal.mo
index 5bf76b99c..b07204c9f 100644
--- a/src/Principal.mo
+++ b/src/Principal.mo
@@ -213,7 +213,7 @@ module {
/// let principal2 = Principal.fromText("un4fu-tqaaa-aaaab-qadjq-cai");
/// assert Principal.compare(principal1, principal2) == #equal;
/// ```
- public func compare(principal1 : Principal, principal2 : Principal) : {
+ public persistent func compare(principal1 : Principal, principal2 : Principal) : {
#less;
#equal;
#greater
diff --git a/src/Queue.mo b/src/Queue.mo
index 8e61fff06..393376887 100644
--- a/src/Queue.mo
+++ b/src/Queue.mo
@@ -526,6 +526,40 @@ module {
}
};
+ /// Returns an iterator over the elements in the queue, in reverse order.
+ /// Iterates from back to front.
+ ///
+ /// Example:
+ /// ```motoko
+ /// import Queue "mo:core/Queue";
+ /// persistent actor {
+ /// let queue = Queue.fromIter(["A", "B", "C"].values());
+ /// transient let iter = Queue.reverseValues(queue);
+ /// assert iter.next() == ?"C";
+ /// assert iter.next() == ?"B";
+ /// assert iter.next() == ?"A";
+ /// assert iter.next() == null;
+ /// }
+ /// ```
+ ///
+ /// Runtime: O(1) for iterator creation, O(n) for full iteration
+ /// Space: O(1)
+ public func reverseValues(queue : Queue) : Iter.Iter {
+ object {
+ var current = queue.back;
+
+ public func next() : ?T {
+ switch (current) {
+ case null null;
+ case (?node) {
+ current := node.previous;
+ ?node.value
+ }
+ }
+ }
+ }
+ };
+
/// Tests whether all elements in the queue satisfy the given predicate.
///
/// Example:
diff --git a/src/Text.mo b/src/Text.mo
index 864b7284e..429b3dfc8 100644
--- a/src/Text.mo
+++ b/src/Text.mo
@@ -300,7 +300,7 @@ module {
/// assert Text.compare("abc", "def") == #less;
/// assert Text.compare("abc", "ABC") == #greater;
/// ```
- public func compare(t1 : Text, t2 : Text) : Order.Order {
+ public persistent func compare(t1 : Text, t2 : Text) : Order.Order {
let c = Prim.textCompare(t1, t2);
if (c < 0) #less else if (c == 0) #equal else #greater
};
diff --git a/src/object-oriented/List.mo b/src/object-oriented/List.mo
new file mode 100644
index 000000000..068d13f19
--- /dev/null
+++ b/src/object-oriented/List.mo
@@ -0,0 +1,205 @@
+import ImperativeList "../List";
+import PureList "../pure/List";
+import Iter "../Iter";
+import Order "../Order";
+
+module {
+ public persistent class List() {
+ let inner = ImperativeList.empty();
+
+ public func toPure() : PureList.List {
+ PureList.fromIter(ImperativeList.values(inner))
+ };
+
+ public func toImperative() : ImperativeList.List {
+ ImperativeList.clone(inner)
+ };
+
+ public func toArray() : [T] {
+ ImperativeList.toArray(inner)
+ };
+
+ public func isEmpty() : Bool {
+ ImperativeList.isEmpty(inner)
+ };
+
+ public func size() : Nat {
+ ImperativeList.size(inner)
+ };
+
+ public func add(element : T) {
+ ImperativeList.add(inner, element)
+ };
+
+ public func get(index : Nat) : T {
+ ImperativeList.at(inner, index)
+ };
+
+ public func set(index : Nat, value : T) {
+ ImperativeList.put(inner, index, value)
+ };
+
+ public func removeLast() : ?T {
+ ImperativeList.removeLast(inner)
+ };
+
+ public func sort(compare : (T, T) -> Order.Order) {
+ ImperativeList.sort(inner, compare)
+ };
+
+ public func addAll(iter : Iter.Iter) {
+ ImperativeList.addAll(inner, iter)
+ };
+
+ public func addRepeat(initValue : T, count : Nat) {
+ ImperativeList.addRepeat(inner, initValue, count)
+ };
+
+ public func contains(equal : (T, T) -> Bool, element : T) : Bool {
+ ImperativeList.contains(inner, equal, element)
+ };
+
+ public func indexOf(equal : (T, T) -> Bool, element : T) : ?Nat {
+ ImperativeList.indexOf(inner, equal, element)
+ };
+
+ public func lastIndexOf(equal : (T, T) -> Bool, element : T) : ?Nat {
+ ImperativeList.lastIndexOf(inner, equal, element)
+ };
+
+ public func findIndex(predicate : T -> Bool) : ?Nat {
+ ImperativeList.findIndex(inner, predicate)
+ };
+
+ public func findLastIndex(predicate : T -> Bool) : ?Nat {
+ ImperativeList.findLastIndex(inner, predicate)
+ };
+
+ public func binarySearch(compare : (T, T) -> Order.Order, element : T) : {
+ #found : Nat;
+ #insertionIndex : Nat
+ } {
+ ImperativeList.binarySearch(inner, compare, element)
+ };
+
+ public func clone() : List {
+ fromImperative(inner)
+ };
+
+ public func clear() {
+ ImperativeList.clear(inner)
+ };
+
+ public func equal(other : List, equal : (T, T) -> Bool) : Bool {
+ ImperativeList.equal(inner, other.internal(), equal)
+ };
+
+ public func compare(other : List, compare : (T, T) -> Order.Order) : Order.Order {
+ ImperativeList.compare(inner, other.internal(), compare)
+ };
+
+ public func values() : Iter.Iter {
+ ImperativeList.values(inner)
+ };
+
+ public func enumerate() : Iter.Iter<(Nat, T)> {
+ ImperativeList.enumerate(inner)
+ };
+
+ public func reverseValues() : Iter.Iter {
+ ImperativeList.reverseValues(inner)
+ };
+
+ public func reverseEnumerate() : Iter.Iter<(Nat, T)> {
+ ImperativeList.reverseEnumerate(inner)
+ };
+
+ public func reverse() : List {
+ fromImperative(ImperativeList.reverse(inner))
+ };
+
+ public func first() : ?T {
+ ImperativeList.first(inner)
+ };
+
+ public func last() : ?T {
+ ImperativeList.last(inner)
+ };
+
+ public func max(compare : (T, T) -> Order.Order) : ?T {
+ ImperativeList.max(inner, compare)
+ };
+
+ public func min(compare : (T, T) -> Order.Order) : ?T {
+ ImperativeList.min(inner, compare)
+ };
+
+ public func forEach(operation : T -> ()) {
+ for (entry in values()) {
+ operation(entry)
+ }
+ };
+
+ public func filter(criterion : T -> Bool) : List {
+ fromImperative(ImperativeList.filter(inner, criterion))
+ };
+
+ // type error [M0200], cannot decide type constructor equality
+ // TODO: Enable when this issue has been fixed: https://github.com/dfinity/motoko/issues/5446
+ // public func map(project : T -> R) : List {
+ // fromImperative(ImperativeList.map(inner, project))
+ // };
+
+ public func all(predicate : T -> Bool) : Bool {
+ ImperativeList.all(inner, predicate)
+ };
+
+ public func any(predicate : T -> Bool) : Bool {
+ ImperativeList.any(inner, predicate)
+ };
+
+ public func toText(elementFormat : T -> Text) : Text {
+ ImperativeList.toText(inner, elementFormat)
+ };
+
+ public func internal() : ImperativeList.List {
+ inner
+ }
+ };
+
+ public persistent func fromImperative(list : ImperativeList.List) : List {
+ fromIter(ImperativeList.values(list))
+ };
+
+ public func fromPure(pure : PureList.List) : List {
+ fromIter(PureList.values(PureList.reverse(pure)))
+ };
+
+ public func fromArray(array : [T]) : List {
+ fromIter(array.values())
+ };
+
+ public persistent func fromIter(iter : Iter.Iter) : List {
+ let result = List();
+ for (element in iter) {
+ result.add(element)
+ };
+ result
+ };
+
+ public func empty() : List {
+ List()
+ };
+
+ public func singleton(element : T) : List {
+ let result = List();
+ result.add(element);
+ result
+ };
+
+ public func repeat(initValue : T, size : Nat) : List {
+ let result = List();
+ result.addRepeat(initValue, size);
+ result
+ }
+}
diff --git a/src/object-oriented/Map.mo b/src/object-oriented/Map.mo
new file mode 100644
index 000000000..d02a7a9c5
--- /dev/null
+++ b/src/object-oriented/Map.mo
@@ -0,0 +1,152 @@
+import Order "../Order";
+import Iter "../Iter";
+import ImperativeMap "../Map";
+import PureMap "../pure/Map";
+import Runtime "../Runtime";
+
+module {
+ public type PersistentCompare = persistent(K, K) -> Order.Order;
+ type TransientCompare = (K, K) -> Order.Order;
+
+ public persistent class Map(comparison : PersistentCompare) {
+ let inner = ImperativeMap.empty();
+
+ public func toPure() : PureMap.Map {
+ PureMap.fromIter(ImperativeMap.entries(inner), comparison : TransientCompare)
+ };
+
+ public func toImperative() : ImperativeMap.Map {
+ ImperativeMap.clone(inner)
+ };
+
+ public func toArray() : [(K, V)] {
+ Iter.toArray(entries())
+ };
+
+ public func isEmpty() : Bool {
+ ImperativeMap.isEmpty(inner)
+ };
+
+ public func size() : Nat {
+ ImperativeMap.size(inner)
+ };
+
+ public func add(key : K, value : V) {
+ ImperativeMap.add(inner, comparison : TransientCompare, key, value)
+ };
+
+ public func containsKey(key : K) : Bool {
+ ImperativeMap.containsKey(inner, comparison : TransientCompare, key)
+ };
+
+ public func get(key : K) : ?V {
+ ImperativeMap.get(inner, comparison : TransientCompare, key)
+ };
+
+ public func remove(key : K) {
+ ImperativeMap.remove(inner, comparison : TransientCompare, key)
+ };
+
+ public func clone() : Map {
+ fromImperative(inner, comparison)
+ };
+
+ public func clear() {
+ ImperativeMap.clear(inner)
+ };
+
+ public func equal(other : Map, equalValue : (V, V) -> Bool) : Bool {
+ ImperativeMap.equal(inner, other.internal(), comparison : TransientCompare, equalValue)
+ };
+
+ public func compare(other : Map, compareValue : (V, V) -> Order.Order) : Order.Order {
+ ImperativeMap.compare(inner, other.internal(), comparison : TransientCompare, compareValue)
+ };
+
+ public func maxEntry() : ?(K, V) {
+ ImperativeMap.maxEntry(inner)
+ };
+
+ public func minEntry() : ?(K, V) {
+ ImperativeMap.minEntry(inner)
+ };
+
+ public func entries() : Iter.Iter<(K, V)> {
+ ImperativeMap.entries(inner)
+ };
+
+ public func reverseEntries() : Iter.Iter<(K, V)> {
+ ImperativeMap.reverseEntries(inner)
+ };
+
+ public func keys() : Iter.Iter {
+ ImperativeMap.keys(inner)
+ };
+
+ public func values() : Iter.Iter {
+ ImperativeMap.values(inner)
+ };
+
+ public func forEach(operation : (K, V) -> ()) {
+ for (entry in entries()) {
+ operation(entry)
+ }
+ };
+
+ public func filter(criterion : (K, V) -> Bool) : Map {
+ fromImperative(ImperativeMap.filter(inner, comparison : TransientCompare, criterion), comparison)
+ };
+
+ // type error [M0200], cannot decide type constructor equality
+ // TODO: Enable when this issue has been fixed: https://github.com/dfinity/motoko/issues/5446
+ // public func map(project : (K, V) -> R) : Map {
+ // fromImperative(ImperativeMap.map(inner, project), compare)
+ // };
+
+ public func all(predicate : (K, V) -> Bool) : Bool {
+ ImperativeMap.all(inner, predicate)
+ };
+
+ public func any(predicate : (K, V) -> Bool) : Bool {
+ ImperativeMap.any(inner, predicate)
+ };
+
+ public func toText(keyFormat : K -> Text, valueFormat : V -> Text) : Text {
+ ImperativeMap.toText(inner, keyFormat, valueFormat)
+ };
+
+ public func internal() : ImperativeMap.Map {
+ inner
+ }
+ };
+
+ public persistent func fromImperative(map : ImperativeMap.Map, compare : PersistentCompare) : Map {
+ fromIter(ImperativeMap.entries(map), compare)
+ };
+
+ public func fromPure(pure : PureMap.Map, compare: PersistentCompare) : Map {
+ fromIter(PureMap.entries(pure), compare)
+ };
+
+ public func fromArray(array: [(K, V)], compare: PersistentCompare): Map {
+ fromIter(array.values(), compare)
+ };
+
+ public persistent func fromIter(iter : Iter.Iter<(K, V)>, compare : PersistentCompare) : Map {
+ let result = Map(compare);
+ for ((key, value) in iter) {
+ result.add(key, value)
+ };
+ result
+ };
+
+ public func empty(compare : PersistentCompare) : Map {
+ Map(compare)
+ };
+
+ public func singleton(compare : PersistentCompare, key : K, value : V) : Map {
+ let result = Map(compare);
+ result.add(key, value);
+ result
+ }
+}
diff --git a/src/object-oriented/Queue.mo b/src/object-oriented/Queue.mo
new file mode 100644
index 000000000..dd63e157f
--- /dev/null
+++ b/src/object-oriented/Queue.mo
@@ -0,0 +1,116 @@
+import ImperativeQueue "../Queue";
+import PureQueue "../pure/Queue";
+import Iter "../Iter";
+import Order "../Order";
+
+module {
+ public persistent class Queue() {
+ let inner = ImperativeQueue.empty();
+
+ public func toPure() : PureQueue.Queue {
+ PureQueue.fromIter(ImperativeQueue.values(inner))
+ };
+
+ public func toImperative() : ImperativeQueue.Queue {
+ ImperativeQueue.clone(inner)
+ };
+
+ public func toArray() : [T] {
+ ImperativeQueue.toArray(inner)
+ };
+
+ public func isEmpty() : Bool {
+ ImperativeQueue.isEmpty(inner)
+ };
+
+ public func size() : Nat {
+ ImperativeQueue.size(inner)
+ };
+
+ public func pushFront(element : T) {
+ ImperativeQueue.pushFront(inner, element)
+ };
+
+ public func pushBack(element : T) {
+ ImperativeQueue.pushBack(inner, element)
+ };
+
+ public func popFront() : ?T {
+ ImperativeQueue.popFront(inner)
+ };
+
+ public func popBack() : ?T {
+ ImperativeQueue.popBack(inner)
+ };
+
+ public func peekFront() : ?T {
+ ImperativeQueue.peekFront(inner)
+ };
+
+ public func peekBack() : ?T {
+ ImperativeQueue.peekBack(inner)
+ };
+
+ public func contains(equal : (T, T) -> Bool, element : T) : Bool {
+ ImperativeQueue.contains(inner, equal, element)
+ };
+
+ public func clone() : Queue {
+ fromImperative(inner)
+ };
+
+ public func clear() {
+ ImperativeQueue.clear(inner)
+ };
+
+ public func values() : Iter.Iter {
+ ImperativeQueue.values(inner)
+ };
+
+ public func reverseValues() : Iter.Iter {
+ ImperativeQueue.reverseValues(inner)
+ };
+
+ public func equal(other : Queue, equal : (T, T) -> Bool) : Bool {
+ ImperativeQueue.equal(inner, other.internal(), equal)
+ };
+
+ public func compare(other : Queue, compare : (T, T) -> Order.Order) : Order.Order {
+ ImperativeQueue.compare(inner, other.internal(), compare)
+ };
+
+ public func internal() : ImperativeQueue.Queue {
+ inner
+ }
+ };
+
+ public persistent func fromImperative(queue : ImperativeQueue.Queue) : Queue {
+ fromIter(ImperativeQueue.values(queue))
+ };
+
+ public func fromPure(pure : PureQueue.Queue) : Queue {
+ fromIter(PureQueue.values(pure))
+ };
+
+ public func fromArray(array : [T]) : Queue {
+ fromIter(array.values())
+ };
+
+ public persistent func fromIter(iter : Iter.Iter) : Queue {
+ let result = Queue();
+ for (element in iter) {
+ result.pushBack(element)
+ };
+ result
+ };
+
+ public func empty() : Queue {
+ Queue()
+ };
+
+ public func singleton(element : T) : Queue {
+ let result = Queue();
+ result.pushBack(element);
+ result
+ }
+}
diff --git a/src/object-oriented/Set.mo b/src/object-oriented/Set.mo
new file mode 100644
index 000000000..a04dd927e
--- /dev/null
+++ b/src/object-oriented/Set.mo
@@ -0,0 +1,140 @@
+import Order "../Order";
+import Iter "../Iter";
+import ImperativeSet "../Set";
+import PureSet "../pure/Set";
+import Runtime "../Runtime";
+
+module {
+ public type PersistentCompare = persistent(T, T) -> Order.Order;
+ type TransientCompare = (T, T) -> Order.Order;
+
+ public persistent class Set(comparison : PersistentCompare) {
+ let inner = ImperativeSet.empty();
+
+ public func toPure() : PureSet.Set {
+ PureSet.fromIter(ImperativeSet.values(inner), comparison : TransientCompare)
+ };
+
+ public func toImperative() : ImperativeSet.Set {
+ ImperativeSet.clone(inner)
+ };
+
+ public func toArray() : [T] {
+ Iter.toArray(values())
+ };
+
+ public func isEmpty() : Bool {
+ ImperativeSet.isEmpty(inner)
+ };
+
+ public func size() : Nat {
+ ImperativeSet.size(inner)
+ };
+
+ public func add(element : T) {
+ ImperativeSet.add(inner, comparison : TransientCompare, element)
+ };
+
+ public func contains(element : T) : Bool {
+ ImperativeSet.contains(inner, comparison : TransientCompare, element)
+ };
+
+ public func remove(element : T) {
+ ImperativeSet.remove(inner, comparison : TransientCompare, element)
+ };
+
+ public func clone() : Set {
+ fromImperative(inner, comparison)
+ };
+
+ public func clear() {
+ ImperativeSet.clear(inner)
+ };
+
+ public func equal(other : Set) : Bool {
+ ImperativeSet.equal(inner, other.internal(), comparison : TransientCompare)
+ };
+
+ public func compare(other : Set) : Order.Order {
+ ImperativeSet.compare(inner, other.internal(), comparison : TransientCompare)
+ };
+
+ public func max() : ?T {
+ ImperativeSet.max(inner)
+ };
+
+ public func min() : ?T {
+ ImperativeSet.min(inner)
+ };
+
+ public func values() : Iter.Iter {
+ ImperativeSet.values(inner)
+ };
+
+ public func reverseValues() : Iter.Iter {
+ ImperativeSet.reverseValues(inner)
+ };
+
+ public func forEach(operation : T -> ()) {
+ for (entry in values()) {
+ operation(entry)
+ }
+ };
+
+ public func filter(criterion : T -> Bool) : Set {
+ fromImperative(ImperativeSet.filter(inner, comparison : TransientCompare, criterion), comparison)
+ };
+
+ // type error [M0200], cannot decide type constructor equality
+ // TODO: Enable when this issue has been fixed: https://github.com/dfinity/motoko/issues/5446
+ // public func map(project : T -> R) : Set {
+ // fromImperative(ImperativeSet.map(inner, project), compare)
+ // };
+
+ public func all(predicate : T -> Bool) : Bool {
+ ImperativeSet.all(inner, predicate)
+ };
+
+ public func any(predicate : T -> Bool) : Bool {
+ ImperativeSet.any(inner, predicate)
+ };
+
+ public func toText(elementFormat : T -> Text) : Text {
+ ImperativeSet.toText(inner, elementFormat)
+ };
+
+ public func internal() : ImperativeSet.Set {
+ inner
+ }
+ };
+
+ public persistent func fromImperative(set : ImperativeSet.Set, compare : PersistentCompare) : Set {
+ fromIter(ImperativeSet.values(set), compare)
+ };
+
+ public func fromPure(pure : PureSet.Set, compare: PersistentCompare) : Set {
+ fromIter(PureSet.values(pure), compare)
+ };
+
+ public func fromArray(array: [T], compare: PersistentCompare): Set {
+ fromIter(array.values(), compare)
+ };
+
+ public persistent func fromIter(iter : Iter.Iter, compare : PersistentCompare) : Set {
+ let result = Set(compare);
+ for (element in iter) {
+ result.add(element)
+ };
+ result
+ };
+
+ public func empty(compare : PersistentCompare) : Set {
+ Set(compare)
+ };
+
+ public func singleton(compare : PersistentCompare, element : T) : Set {
+ let result = Set(compare);
+ result.add(element);
+ result
+ }
+}
diff --git a/src/object-oriented/Stack.mo b/src/object-oriented/Stack.mo
new file mode 100644
index 000000000..f2f23417c
--- /dev/null
+++ b/src/object-oriented/Stack.mo
@@ -0,0 +1,104 @@
+import ImperativeStack "../Stack";
+import PureList "../pure/List";
+import Iter "../Iter";
+import Order "../Order";
+
+module {
+ persistent class Stack() {
+ let inner = ImperativeStack.empty();
+
+ public func toPure() : PureList.List {
+ PureList.fromIter(ImperativeStack.values(inner))
+ };
+
+ public func toImperative() : ImperativeStack.Stack {
+ ImperativeStack.clone(inner)
+ };
+
+ public func toArray() : [T] {
+ Iter.toArray(values());
+ };
+
+ public func isEmpty() : Bool {
+ ImperativeStack.isEmpty(inner)
+ };
+
+ public func size() : Nat {
+ ImperativeStack.size(inner)
+ };
+
+ public func push(element : T) {
+ ImperativeStack.push(inner, element)
+ };
+
+ public func pop() : ?T {
+ ImperativeStack.pop(inner)
+ };
+
+ public func peek() : ?T {
+ ImperativeStack.peek(inner)
+ };
+
+ public func contains(equal : (T, T) -> Bool, element : T) : Bool {
+ ImperativeStack.contains(inner, equal, element)
+ };
+
+ public func clone() : Stack {
+ fromImperative(inner)
+ };
+
+ public func clear() {
+ ImperativeStack.clear(inner)
+ };
+
+ public func values() : Iter.Iter {
+ ImperativeStack.values(inner)
+ };
+
+ public func reverseValues() : Iter.Iter {
+ Iter.reverse(values());
+ };
+
+ public func equal(other : Stack, equal : (T, T) -> Bool) : Bool {
+ ImperativeStack.equal(inner, other.internal(), equal)
+ };
+
+ public func compare(other : Stack, compare : (T, T) -> Order.Order) : Order.Order {
+ ImperativeStack.compare(inner, other.internal(), compare)
+ };
+
+ public func internal() : ImperativeStack.Stack {
+ inner
+ }
+ };
+
+ public persistent func fromImperative(Stack : ImperativeStack.Stack) : Stack {
+ fromIter(ImperativeStack.values(Stack))
+ };
+
+ public func fromPure(pure : PureList.List) : Stack {
+ fromIter(PureList.values(pure))
+ };
+
+ public func fromArray(array : [T]) : Stack {
+ fromIter(array.values())
+ };
+
+ public persistent func fromIter(iter : Iter.Iter) : Stack {
+ let result = Stack();
+ for (element in iter) {
+ result.push(element)
+ };
+ result
+ };
+
+ public func empty() : Stack {
+ Stack()
+ };
+
+ public func singleton(element : T) : Stack {
+ let result = Stack();
+ result.push(element);
+ result
+ }
+}
diff --git a/test/Queue.test.mo b/test/Queue.test.mo
index 92b360a16..dd277cf09 100644
--- a/test/Queue.test.mo
+++ b/test/Queue.test.mo
@@ -87,6 +87,13 @@ suite(
}
);
+ test(
+ "reverseValues",
+ func() {
+ assert Iter.toArray(Queue.reverseValues(Queue.empty())) == []
+ }
+ );
+
test(
"equal",
func() {
@@ -606,6 +613,21 @@ suite(
assert counter == numberOfSteps;
expect.nat(Queue.size(queue)).equal((numberOfSteps + 1) / 2)
}
+ );
+
+ test(
+ "reverseValues",
+ func() {
+ let queue = Queue.empty();
+ for (number in Nat.range(0, numberOfSteps)) {
+ Queue.pushBack(queue, number)
+ };
+ var index = 0;
+ for (number in Queue.reverseValues(queue)) {
+ index += 1;
+ assert number == numberOfSteps - index;
+ }
+ }
)
}
);
diff --git a/test/ts/importAll.ts b/test/ts/importAll.ts
index 185ec4572..0de9eaa94 100644
--- a/test/ts/importAll.ts
+++ b/test/ts/importAll.ts
@@ -20,7 +20,7 @@ if (moFiles.length === 0) {
const source = moFiles
.map((f) => {
const name = f.replace(/\.mo$/, "");
- return `import _${name.replace("/", "_")} "../../src/${name}";\n`;
+ return `import _${name.replace(/[\/\-]/g, "_")} "../../src/${name}";\n`;
})
.join("");
diff --git a/test/ts/validate/version.ts b/test/ts/validate/version.ts
index 7c4263de0..bbfbf33f0 100644
--- a/test/ts/validate/version.ts
+++ b/test/ts/validate/version.ts
@@ -39,7 +39,7 @@ async function getReadmeVersions(): Promise<{
async function main() {
try {
- const [mopsVersion, mocVersion, readmeVersions] = await Promise.all([
+ const [mopsVersion, _mocVersion, readmeVersions] = await Promise.all([
getMopsVersion(),
getMocVersion(),
getReadmeVersions(),