From 0e3a60a3cbaf9659a33375d242712bb27af91089 Mon Sep 17 00:00:00 2001 From: Claudio Russo Date: Tue, 4 Jun 2024 14:03:03 +0100 Subject: [PATCH] use more tail recursion in List.mo --- src/List.mo | 62 ++++++++++++++++++++++++++-------------------- test/Deque.test.mo | 2 +- 2 files changed, 36 insertions(+), 28 deletions(-) diff --git a/src/List.mo b/src/List.mo index 10369a8f..8d2e97ff 100644 --- a/src/List.mo +++ b/src/List.mo @@ -193,10 +193,13 @@ module { /// Space: O(size) /// *Runtime and space assumes that `f` runs in O(1) time and space. public func map(l : List, f : T -> U) : List { - switch l { - case null { null }; - case (?(h, t)) { ?(f(h), map(t, f)) } - } + func go(acc : List, l : List) : List { + 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 @@ -211,16 +214,19 @@ module { /// /// Space: O(size) public func filter(l : List, f : T -> Bool) : List { - switch l { - case null { null }; - case (?(h, t)) { - if (f(h)) { - ?(h, filter(t, f)) - } else { - filter(t, f) + func go(acc : List, l : List) : List { + 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`). @@ -277,15 +283,18 @@ module { /// /// *Runtime and space assumes that `f` runs in O(1) time and space. public func mapFilter(l : List, f : T -> ?U) : List { - switch l { - case null { null }; - case (?(h, t)) { - switch (f(h)) { - case null { mapFilter(t, f) }; - case (?h_) { ?(h_, mapFilter(t, f)) } + func go(acc : List, l : List) : List { + 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 @@ -789,18 +798,17 @@ module { /// Space: O(n) public func split(n : Nat, xs : List) : (List, List) { if (n == 0) { (null, xs) } else { - func rec(n : Nat, xs : List) : (List, List) { - switch (pop(xs)) { - case (null, _) { (null, null) }; - case (?h, t) { - if (n == 1) { (make(h), t) } else { - let (l, r) = rec(n - 1, t); - (push(h, l), r) + func rec(n : Nat, acc : List, xs : List) : (List, List) { + 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) } }; diff --git a/test/Deque.test.mo b/test/Deque.test.mo index 7e481cba..8ff6820a 100644 --- a/test/Deque.test.mo +++ b/test/Deque.test.mo @@ -513,7 +513,7 @@ run( [ test( "random insertion and deletion", - isSorted(randomInsertionDeletion(1000)), + isSorted(randomInsertionDeletion(10000)), M.equals(T.bool(true)) ) ]