Skip to content

Commit

Permalink
use more tail recursion in List.mo
Browse files Browse the repository at this point in the history
  • Loading branch information
crusso committed Jun 4, 2024
1 parent f2b7a63 commit 0e3a60a
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 28 deletions.
62 changes: 35 additions & 27 deletions src/List.mo
Original file line number Diff line number Diff line change
Expand Up @@ -193,10 +193,13 @@ module {
/// Space: O(size)
/// *Runtime and space assumes that `f` runs in O(1) time and space.
public func map<T, U>(l : List<T>, f : T -> U) : List<U> {
switch l {
case null { null };
case (?(h, t)) { ?(f(h), map<T, U>(t, f)) }
}
func go(acc : List<U>, l : List<T>) : List<U> {
switch l {
case null { reverse(acc) };
case (?(h, t)) { go(?(f(h), acc), t) }
}
};
go(null, l)
};

/// Create a new list with only those elements of the original list for which
Expand All @@ -211,16 +214,19 @@ module {
///
/// Space: O(size)
public func filter<T>(l : List<T>, f : T -> Bool) : List<T> {
switch l {
case null { null };
case (?(h, t)) {
if (f(h)) {
?(h, filter<T>(t, f))
} else {
filter<T>(t, f)
func go(acc : List<T>, l : List<T>) : List<T> {
switch l {
case null { reverse(acc) };
case (?(h, t)) {
if (f(h)) {
go(?(h, acc), t)
} else {
go(acc, t)
}
}
}
}
};
go(null, l);
};

/// Create two new lists from the results of a given function (`f`).
Expand Down Expand Up @@ -277,15 +283,18 @@ module {
///
/// *Runtime and space assumes that `f` runs in O(1) time and space.
public func mapFilter<T, U>(l : List<T>, f : T -> ?U) : List<U> {
switch l {
case null { null };
case (?(h, t)) {
switch (f(h)) {
case null { mapFilter<T, U>(t, f) };
case (?h_) { ?(h_, mapFilter<T, U>(t, f)) }
func go(acc : List<U>, l : List<T>) : List<U> {
switch l {
case null { reverse(acc) };
case (?(h, t)) {
switch (f(h)) {
case null { go(acc, t) };
case (?h_) { go(?(h_,acc), t) }
}
}
}
}
};
go(null, l);
};

/// Maps a Result-returning function `f` over a List and returns either
Expand Down Expand Up @@ -789,18 +798,17 @@ module {
/// Space: O(n)
public func split<T>(n : Nat, xs : List<T>) : (List<T>, List<T>) {
if (n == 0) { (null, xs) } else {
func rec(n : Nat, xs : List<T>) : (List<T>, List<T>) {
switch (pop<T>(xs)) {
case (null, _) { (null, null) };
case (?h, t) {
if (n == 1) { (make<T>(h), t) } else {
let (l, r) = rec(n - 1, t);
(push<T>(h, l), r)
func rec(n : Nat, acc : List<T>, xs : List<T>) : (List<T>, List<T>) {
switch xs {
case null { (reverse(acc), null) };
case (?(h, t)) {
if (n == 1) { (reverse(?(h, acc)), t) } else {
rec(n - 1, ?(h, acc), t);
}
}
}
};
rec(n, xs)
rec(n, null, xs)
}
};

Expand Down
2 changes: 1 addition & 1 deletion test/Deque.test.mo
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@ run(
[
test(
"random insertion and deletion",
isSorted(randomInsertionDeletion(1000)),
isSorted(randomInsertionDeletion(10000)),
M.equals(T.bool(true))
)
]
Expand Down

0 comments on commit 0e3a60a

Please sign in to comment.