/* * Copyright 2021 Jakob Schneider Villumsen * * Use of this source code is governed by the Apache 2.0 license * that can be found in the LICENSE.md file. */pubmod DelayMap {import java.lang.RuntimepubenumDelayMap[k, v] {case DMap(RedBlackTree[k, Lazy[v]]) }instanceEq[DelayMap[k, v]] withEq[k], Eq[v] {pubdefeq(m1: DelayMap[k, v], m2: DelayMap[k, v]): Bool =DelayMap.toList(m1) ==DelayMap.toList(m2) }instanceOrder[DelayMap[k, v]] withOrder[k], Order[v] {pubdefcompare(x: DelayMap[k, v], y: DelayMap[k, v]): Comparison =DelayMap.toList(x) <=>DelayMap.toList(y) }instanceToString[DelayMap[k, v]] withToString[k], ToString[v] {pubdeftoString(m: DelayMap[k, v]): String = DelayMap.toString(m) }instanceIndexable[DelayMap[k, v]] withOrder[k] {typeIdx = ktypeElm = vtypeAef = KeyNotFoundpubdefget(t: DelayMap[k, v], i: k): v \ KeyNotFound = matchDelayMap.get(i, t) {case Some(v) => vcase None => KeyNotFound.keyNotFound("key not found") } }instanceFunctor[DelayMap[k]] {pubdefmap(f: v1 -> v2 \ ef, m: DelayMap[k, v1]): DelayMap[k, v2] \ ef = DelayMap.map(f, m) }instanceFoldable[DelayMap[k]] {pubdeffoldLeft(f: (b, v) -> b \ ef, s: b, m: DelayMap[k, v]): b \ ef = DelayMap.foldLeft(f, s, m)pubdeffoldRight(f: (v, b) -> b \ ef, s: b, m: DelayMap[k, v]): b \ ef = DelayMap.foldRight(f, s, m) redef isEmpty(m: DelayMap[k, v]): Bool = DelayMap.isEmpty(m) }instanceIterable[DelayMap[k, v]] {typeElm = (k, v)pubdefiterator(rc: Region[r], m: DelayMap[k, v]): Iterator[(k, v), r, r] \ r =DelayMap.iterator(rc, m) }instanceForEach[DelayMap[k, v]] {typeElm = (k, v)pubdefforEach(f: ((k, v)) -> Unit \ ef, m: DelayMap[k, v]): Unit \ ef = DelayMap.forEach(k -> v -> f((k, v)), m) }////// Returns a string representation of the given `DelayMap` `m`.///@ExperimentalpubdeftoString(m: DelayMap[k, v]): StringwithToString[k], ToString[v] = regionrc {"DelayMap#{"+ (DelayMap.iterator(rc, m) |> Iterator.map(match (k, v) -> "${k} => ${v}") |> Iterator.join(", ")) +"}" }////// Returns the number of threads to use for parallel evaluation.////// # SAFETY:/// This accesses the runtime environment, which is an effect./// It is assumed that this function is only used in contexts/// where this effect is not observable outside of the DelayMap module.///defthreads(): Int32 = {// Note: We use a multiple of the number of physical cores for better performance.letmultiplier = 4;multiplier* Runtime.getRuntime().availableProcessors() }////// Determines whether to use parallel evaluation.////// By default we only enable parallel evaluation if the map has a certain size.///defuseParallelEvaluation(m: DelayMap[k, v]): Bool =let DMap(t) = m;letminSize = Int32.pow(base = 2, RedBlackTree.blackHeight(t));minSize>=1024////// Returns the empty map.///@Experimentalpubdefempty(): DelayMap[k, v] = DMap(RedBlackTree.empty())////// Returns the singleton map where key `k` is mapped to value `v`.///@Experimentalpubdefsingleton(k: k, v: v): DelayMap[k, v] withOrder[k] =insert(k, v, empty())////// Returns the number of keys in `m`.///@Experimentalpubdefsize(m: DelayMap[k, v]): Int32 =let DMap(t) = m;RedBlackTree.size(t)////// Returns `true` if and only if `m` is the empty map, i.e. `Map(Nil)`.///@ExperimentalpubdefisEmpty(m: DelayMap[k, v]): Bool =let DMap(t) = m;RedBlackTree.isEmpty(t)////// Returns `true` if and only if `m` is a non-empty map.///@ExperimentalpubdefnonEmpty(m: DelayMap[k, v]): Bool = notisEmpty(m)////// Returns `m` with `k => v`.///@Experimentalpubdefinsert(k: k, v: v, m: DelayMap[k, v]): DelayMap[k, v] withOrder[k] =let DMap(t) = m; DMap(RedBlackTree.insert(k, lazyv, t))////// Returns `Some(v)` if `k => v` is in `m`.////// Otherwise returns `None`.///@Experimentalpubdefget(k: k, m: DelayMap[k, v]): Option[v] withOrder[k] =let DMap(t) = m;matchRedBlackTree.get(k, t) {case None => Nonecase Some(x) => Some(forcex) }////// Returns `v` if `k => v` is in `m`.////// Otherwise, returns `d`.///@ExperimentalpubdefgetWithDefault(k: k, d: v, m: DelayMap[k, v]): vwithOrder[k] =Option.getWithDefault(d, get(k, m))////// Returns the number of mappings `k => v` in `m` that satisfy the predicate `f`.////// Purity reflective: Runs in parallel when given a pure function `f`.///@Experimental@ParallelWhenPurepubdefcount(f: (k, v) -> Bool \ ef, m: DelayMap[k, v]): Int32 \ ef =defc() = foldLeftWithKey((b, k, v) -> if (f(k, v)) b+1elseb, 0, m);matchpurityOf2(f) {case Purity2.Pure(g) =>if (useParallelEvaluation(m))leth = (k, v) -> g(k, forcev);let DMap(t) = m;RedBlackTree.parCount(h, t)elsec()case Purity2.Impure(_) => c() }////// Returns `true` if and only if `m` contains the key `k`.///@ExperimentalpubdefmemberOf(k: k, m: DelayMap[k, v]): BoolwithOrder[k] =let DMap(t) = m;RedBlackTree.memberOf(k, t)////// Optionally finds `k => v` where `k` is the smallest key according to the `Order` instance of `k`.////// Returns `None` if `m` is empty.///@ExperimentalpubdefminimumKey(m: DelayMap[k, v]): Option[(k, v)] =let DMap(t) = m;matchRedBlackTree.minimumKey(t) {case None => Nonecase Some((k, v)) => Some((k, forcev)) }////// Optionally finds `k => v` where `k` is the smallest key according to the given comparator `cmp`.////// Returns `None` if `m` is empty.////// Purity reflective: Runs in parallel when given a pure function `cmp`.///@Experimental@ParallelWhenPurepubdefminimumKeyBy(cmp: (k, k) -> Comparison \ ef, m: DelayMap[k, v]): Option[(k, v)] \ ef =defmin() = reduceLeftWithKey((kl, vl, kr, vr) -> if (cmp(kl, kr) == Comparison.LessThan) (kl, vl) else (kr, vr), m);matchpurityOf2(cmp) {case Purity2.Pure(g) =>if (useParallelEvaluation(m))leth = (kl, _, kr, _) -> g(kl, kr);let DMap(t) = m;letres = RedBlackTree.parMinimumBy(h, t);matchres {case None => Nonecase Some((k, v)) => Some((k, forcev)) }elsemin()case Purity2.Impure(_) => min() }////// Optionally finds `k => v` where `v` is the smallest value.////// Returns `None` if `m` is empty.///@Experimental@ParallelpubdefminimumValue(m: DelayMap[k, v]): Option[(k, v)] withOrder[v] =minimumValueBy((x, y) -> x<=>y, m)////// Optionally finds `k => v` where `k` is the smallest value according to the given comparator `cmp`.////// Returns `None` if `m` is empty.////// Purity reflective: Runs in parallel when given a pure function `cmp`.///@Experimental@ParallelWhenPurepubdefminimumValueBy(cmp: (v, v) -> Comparison \ ef, m: DelayMap[k, v]): Option[(k, v)] \ ef =defmin() = reduceLeftWithKey((kl, vl, kr, vr) -> if (cmp(vl, vr) == Comparison.LessThan) (kl, vl) else (kr, vr), m);matchpurityOf2(cmp) {case Purity2.Pure(g) =>if (useParallelEvaluation(m))leth = (_, vl, _, vr) -> g(forcevl, forcevr);let DMap(t) = m;letres = RedBlackTree.parMinimumBy(h, t);matchres {case None => Nonecase Some((k, v)) => Some((k, forcev)) }elsemin()case Purity2.Impure(_) => min() }////// Optionally finds `k => v` where `k` is the largest key according to the `Order` instance of `k`.////// Returns `None` if `m` is empty.///@ExperimentalpubdefmaximumKey(m: DelayMap[k, v]): Option[(k, v)] =let DMap(t) = m;matchRedBlackTree.maximumKey(t) {case None => Nonecase Some((k, v)) => Some((k, forcev)) }////// Optionally finds `k => v` where `k` is the largest key according to the given comparator `cmp`.////// Returns `None` if `m` is empty.////// Purity reflective: Runs in parallel when given a pure function `cmp`.///@Experimental@ParallelWhenPurepubdefmaximumKeyBy(cmp: (k, k) -> Comparison \ ef, m: DelayMap[k, v]): Option[(k, v)] \ ef =defmax() = reduceLeftWithKey((kl, vl, kr, vr) -> if (cmp(kl, kr) == Comparison.GreaterThan) (kl, vl) else (kr, vr), m);matchpurityOf2(cmp) {case Purity2.Pure(g) =>if (useParallelEvaluation(m))leth = (kl, _, kr, _) -> g(kl, kr);let DMap(t) = m;letres = RedBlackTree.parMaximumBy(h, t);matchres {case None => Nonecase Some((k, v)) => Some((k, forcev)) }elsemax()case Purity2.Impure(_) => max() }////// Optionally finds `k => v` where `v` is the largest value.////// Returns `None` if `m` is empty.///@Experimental@ParallelpubdefmaximumValue(m: DelayMap[k, v]): Option[(k, v)] withOrder[v] =maximumValueBy((x, y) -> x<=>y, m)////// Optionally finds `k => v` where `k` is the largest value according to the given comparator `cmp`.////// Returns `None` if `m` is empty.////// Purity reflective: Runs in parallel when given a pure function `cmp`.///@Experimental@ParallelWhenPurepubdefmaximumValueBy(cmp: (v, v) -> Comparison \ ef, m: DelayMap[k, v]): Option[(k, v)] \ ef =defmax() = reduceLeftWithKey((kl, vl, kr, vr) -> if (cmp(vl, vr) == Comparison.GreaterThan) (kl, vl) else (kr, vr), m);matchpurityOf2(cmp) {case Purity2.Pure(g) =>if (useParallelEvaluation(m))leth = (_, vl, _, vr) -> g(forcevl, forcevr);let DMap(t) = m;letres = RedBlackTree.parMaximumBy(h, t);matchres {case None => Nonecase Some((k, v)) => Some((k, forcev)) }elsemax()case Purity2.Impure(_) => max() }////// Returns the keys of `m`.///@ExperimentalpubdefkeysOf(m: DelayMap[k, v]): Set[k] withOrder[k] =foldLeftWithKey((acc, k, _) -> Set.insert(k, acc), Set.empty(), m)////// Returns the values of `m`.///@ExperimentalpubdefvaluesOf(m: DelayMap[k, v]): List[v] =foldRight((v, acc) -> v :: acc, Nil, m)////// Removes the mapping `k` from the map `m`.///@Experimentalpubdefremove(k: k, m: DelayMap[k, v]): DelayMap[k, v] withOrder[k] =let DMap(t) = m; DMap(RedBlackTree.remove(k, t))////// Updates `m` with `k => f(v, v1)` if `k => v1` is in `m`.////// Otherwise, updates `m` with `k => v`.///@Experimental@LazyWhenPurepubdefinsertWith(f: (v, v) -> v \ ef, k: k, v: v, m: DelayMap[k, v]): DelayMap[k, v] \ efwithOrder[k] =insertWithKey((_, v1, v2) -> f(v1, v2), k, v, m)////// Updates `m` with `k => f(k, v, v1)` if `k => v1` is in `m`.////// Otherwise, updates `m` with `k => v`.///@Experimental@LazyWhenPurepubdefinsertWithKey(f: (k, v, v) -> v \ ef, k: k, v: v, m: DelayMap[k, v]): DelayMap[k, v] \ efwithOrder[k] =matchpurityOf3(f) {case Purity3.Pure(g) => insertWithKeyL(g, k, v, m)case Purity3.Impure(g) => insertWithKeyE(g, k, v, m) }////// Helper function for `insertWithKey`. Applies `f` lazily.///@LazydefinsertWithKeyL(f: (k, v, v) -> v, k: k, v: v, m: DelayMap[k, v]): DelayMap[k, v] withOrder[k] =let DMap(t) = m;letf1 = (k1, v1, v2) -> lazyf(k1, forcev1, forcev2); DMap(RedBlackTree.insertWith(f1, k, lazyv, t))////// Helper function for `insertWithKey`. Applies `f` eagerly.///definsertWithKeyE(f: (k, v, v) -> v \ ef, k: k, v: v, m: DelayMap[k, v]): DelayMap[k, v] \ efwithOrder[k] =let DMap(t) = m;letf1 = (k1, v1, v2) -> {letx = f(k1, forcev1, forcev2);lazyx }; DMap(RedBlackTree.insertWith(f1, k, lazyv, t))////// Returns a map with mappings `k => f(v)` for every `k => v` in `m`.////// Purity reflective:/// - Runs in parallel when given a pure function `f`./// - Applies `f` lazily if `f` is pure.///@Experimental@ParallelWhenPure@LazyWhenPurepubdefmap(f: v1 -> v2 \ ef, m: DelayMap[k, v1]): DelayMap[k, v2] \ ef =mapWithKey((_, v) -> f(v), m)////// Returns a map with mappings `k => f(k, v)` for every `k => v` in `m`.////// Purity reflective:/// - Runs in parallel when given a pure function `f`./// - Applies `f` lazily if `f` is pure.///@Experimental@ParallelWhenPure@LazyWhenPurepubdefmapWithKey(f: (k, v1) -> v2 \ ef, m: DelayMap[k, v1]): DelayMap[k, v2] \ ef =matchpurityOf2(f) {case Purity2.Pure(g) => mapWithKeyL(g, m)case Purity2.Impure(g) => mapWithKeyE(g, m) }////// Helper function for `mapWithKey`. Applies `f` lazily.////// Purity reflective: Runs in parallel when given a pure function `f`.///@ParallelWhenPure@LazydefmapWithKeyL(f: (k, v1) -> v2, m: DelayMap[k, v1]): DelayMap[k, v2] =let DMap(t) = m;letg = (k, v) -> lazyf(k, forcev); DMap(RedBlackTree.mapWithKey(g, t))////// Helper function for `mapWithKey`. Applies `f` eagerly.///defmapWithKeyE(f: (k, v1) -> v2 \ ef, m: DelayMap[k, v1]): DelayMap[k, v2] \ ef =letg = (k, v) -> {letx1 = f(k, forcev);lazyx1 };let_ = parallelForce(m);let DMap(t) = m; DMap(RedBlackTree.mapWithKey(g, t))////// Forces `m` in parallel if it is big, otherwise returns `m`.///@ParalleldefparallelForce(m: DelayMap[k, v]): Unit =if (useParallelEvaluation(m))forceAll(m)else()////// Forces **all values** in `m`.///@Experimental@ParallelpubdefforceAll(m: DelayMap[k, v]): Unit =use RedBlackTree.Node;defseqLoop(tt) = matchtt {case Node(_, a, _, v, b) =>let_ = seqLoop(a);let_ = forcev;seqLoop(b)case_ => () };defparLoop(n, tt) = {if (n<=1)seqLoop(tt)elsematchtt {case Node(_, a, _, v, b) =>par (_ <- parLoop((n-2) /2, a); // We divide the rest of the threads as follows:_ <- parLoop((n-2) /2, b); // We spawn two new threads leaving us with n - 2_ <- forcev// that we distribute over the two spanned threads. ) yield()case_ => () } };let DMap(t) = m;if (useParallelEvaluation(m))parLoop(threads()-1, t)elseseqLoop(t)////// Returns a map of all mappings `k => v` in `m` where `v` satisfies the predicate `f`.///@Experimentalpubdeffilter(f: v -> Bool \ ef, m: DelayMap[k, v]): DelayMap[k, v] \ efwithOrder[k] =filterWithKey((_, v) -> f(v), m)////// Returns a map of all mappings `k => v` in `m` where `(k, v)` satisfies the predicate `f`.///@ExperimentalpubdeffilterWithKey(f: (k, v) -> Bool \ ef, m: DelayMap[k, v]): DelayMap[k, v] \ efwithOrder[k] =foldLeftWithKey((acc, k, v) -> if (f(k, v)) insert(k, v, acc) elseacc, empty(), m)////// Returns the left-biased union of `m1` and `m2`.////// That is, key collisions are resolved by taking the mapping from `m1`.///@Experimental@Lazypubdefunion(m1: DelayMap[k, v], m2: DelayMap[k, v]): DelayMap[k, v] withOrder[k] =unionWithKey((_, v1, _) -> v1, m1, m2)////// Returns the union of `m1` and `m2` where key collisions are resolved with the merge function `f`.////// Purity reflective: Applies `f` lazily if `f` is pure.///@Experimental@LazyWhenPurepubdefunionWith(f: (v, v) -> v \ ef, m1: DelayMap[k, v], m2: DelayMap[k, v]): DelayMap[k, v] \ efwithOrder[k] =unionWithKey((_, v1, v2) -> f(v1, v2), m1, m2)////// Returns the union of `m1` and `m2` where key collisions are resolved with the merge function `f`, taking both the key and values.////// Purity reflective: Applies `f` lazily if `f` is pure.///@Experimental@LazyWhenPurepubdefunionWithKey(f: (k, v, v) -> v \ ef, m1: DelayMap[k, v], m2: DelayMap[k, v]): DelayMap[k, v] \ efwithOrder[k] =matchpurityOf3(f) {case Purity3.Pure(g) => unionWithKeyL(g, m1, m2)case Purity3.Impure(g) => unionWithKeyE(g, m1, m2) }////// Helper function for `unionWithKey`. Applies `f` lazily.///@LazydefunionWithKeyL(f: (k, v, v) -> v, m1: DelayMap[k, v], m2: DelayMap[k, v]): DelayMap[k, v] withOrder[k] =use RedBlackTree.{blackHeight, foldRight, insertWith};let DMap(xs) = m1;let DMap(ys) = m2;letf1 = (k, v1, v2) -> lazy (f(k, forcev1, forcev2));if (blackHeight(xs) <blackHeight(ys)) DMap(foldRight((k, v, acc) -> insertWith(f1, k, v, acc), ys, xs))else DMap(foldRight((k, v, acc) -> insertWith((_, v1, v2) -> f1(k, v2, v1), k, v, acc), xs, ys))////// Helper function for `unionWithKey`. Applies `f` eagerly.///defunionWithKeyE(f: (k, v, v) -> v \ ef, m1: DelayMap[k, v], m2: DelayMap[k, v]): DelayMap[k, v] \ efwithOrder[k] =use RedBlackTree.{blackHeight, foldRight, insertWith};let DMap(xs) = m1;let DMap(ys) = m2;letf1 = (k, v1, v2) -> {letx = f(k, forcev1, forcev2);lazyx };if (blackHeight(xs) <blackHeight(ys))let_ = parallelForce(m1); DMap(foldRight((k, v, acc) -> insertWith(f1, k, v, acc), ys, xs))elselet_ = parallelForce(m2); DMap(foldRight((k, v, acc) -> insertWith((_, v1, v2) -> f1(k, v2, v1), k, v, acc), xs, ys))////// Applies `f` to a start value `s` and all values in `m` going from left to right.////// That is, the result is of the form: `f(...f(f(s, v1), v2)..., vn)`.///@ExperimentalpubdeffoldLeft(f: (b, v) -> b \ ef, s: b, m: DelayMap[k, v]): b \ ef =foldLeftWithKey((acc, _, v) -> f(acc, v), s, m)////// Applies `f` to a start value `s` and all key-value pairs in `m` going from left to right.////// That is, the result is of the form: `f(...f(f(s, k1, v1), k2, v2)..., vn)`.///@ExperimentalpubdeffoldLeftWithKey(f: (b, k, v) -> b \ ef, s: b, m: DelayMap[k, v]): b \ ef =let_ = parallelForce(m);let DMap(t) = m;letf1 = (b, k, v) -> f(b, k, forcev);RedBlackTree.foldLeft(f1, s, t)////// Applies `f` to a start value `s` and all values in `m` going from right to left.////// That is, the result is of the form: `f(v1, ...f(vn-1, f(vn, s)))`.///@ExperimentalpubdeffoldRight(f: (v, b) -> b \ ef, s: b, m: DelayMap[k, v]): b \ ef =foldRightWithKey((_, v, acc) -> f(v, acc), s, m)////// Applies `f` to a start value `s` and all key-value pairs in `m` going from right to left.////// That is, the result is of the form: `f(k1, v1, ...f(kn-1, vn-1, f(kn, vn, s)))`.///@ExperimentalpubdeffoldRightWithKey(f: (k, v, b) -> b \ ef, s: b, m: DelayMap[k, v]): b \ ef =let_ = parallelForce(m);let DMap(t) = m;letf1 = (k1, v1, b1) -> f(k1, forcev1, b1);RedBlackTree.foldRight(f1, s, t)////// Applies `f` to all values in `m` going from left to right until a single value `v` is obtained. Returns `Some(v)`.////// That is, the result is of the form: `Some(f(...f(f(v1, v2), v3)..., vn))`////// Returns `None` if `m` is the empty map.///@ExperimentalpubdefreduceLeft(f: (v, v) -> v \ ef, m: DelayMap[k, v]): Option[v] \ ef =reduceLeftWithKey((k, v1, _, v2) -> (k, f(v1, v2)), m) |> Option.map(snd)////// Applies `f` to all mappings in `m` going from left to right until a single mapping `(k, v)` is obtained. Returns `Some((k, v))`.////// That is, the result is of the form: `Some(f(...f(f(k1, v1, k2, v2), k3, v3)..., kn, vn))`////// Returns `None` if `m` is the empty map.///@ExperimentalpubdefreduceLeftWithKey(f: (k, v, k, v) -> (k, v) \ ef, m: DelayMap[k, v]): Option[(k, v)] \ ef =let_ = parallelForce(m);let DMap(t) = m;letf1 = (k1, v1, k2, v2) -> {let (k, v) = f(k1, forcev1, k2, forcev2); (k, lazyv) };matchRedBlackTree.reduceLeft(f1, t) {case Some((k, v)) => Some((k, forcev))case None => None }////// Applies `f` to all values in `m` going from right to left until a single value `v` is obtained. Returns `Some(v)`.////// That is, the result is of the form: `Some(f(v1, ...f(vn-2, f(vn-1, vn))...))`////// Returns `None` if `m` is the empty DelayMap.///@ExperimentalpubdefreduceRight(f: (v, v) -> v \ ef, m: DelayMap[k, v]): Option[v] \ ef =reduceRightWithKey((k, v1, _, v2) -> (k, f(v1, v2)), m) |> Option.map(snd)////// Applies `f` to all mappings in `m` going from right to left until a single mapping `(k, v)` is obtained. Returns `Some((k, v))`.////// That is, the result is of the form: `Some(f(k1, v1, ...f(kn-2, vn-2, f(kn-1, vn-1, kn, vn))...))`////// Returns `None` if `m` is the empty DelayMap.///@ExperimentalpubdefreduceRightWithKey(f: (k, v, k, v) -> (k, v) \ ef, m: DelayMap[k, v]): Option[(k, v)] \ ef =let_ = parallelForce(m);let DMap(t) = m;letf1 = (k1, v1, k2, v2) -> {let (k, v) = f(k1, forcev1, k2, forcev2); (k, lazyv) };matchRedBlackTree.reduceRight(f1, t) {case Some((k, v)) => Some((k, forcev))case None => None }////// Updates `m` with `k => f(v)` if `k => v` is in `m`. Otherwise, returns `m`.////// Purity reflective: Applies `f` lazily if `f` is pure.///@Experimental@LazyWhenPurepubdefadjust(f: v -> v \ ef, k: k, m: DelayMap[k, v]): DelayMap[k, v] \ efwithOrder[k] =adjustWithKey((_, v1) -> f(v1), k, m)////// Updates `m` with `k => f(k, v)` if `k => v` is in `m`. Otherwise, returns `m`.////// Purity reflective: Applies `f` lazily if `f` is pure.///@Experimental@LazyWhenPurepubdefadjustWithKey(f: (k, v) -> v \ ef, k: k, m: DelayMap[k, v]): DelayMap[k, v] \ efwithOrder[k] =updateWithKey((k1, v) -> Some(f(k1, v)), k, m)////// Updates `m` with `k => v1` if `k => v` is in `m` and `f(v) = Some(v1)`. Otherwise, returns `m`.////// Purity reflective: Applies `f` lazily if `f` is pure.///@Experimental@LazyWhenPurepubdefupdate(f: v -> Option[v] \ ef, k: k, m: DelayMap[k, v]): DelayMap[k, v] \ efwithOrder[k] =updateWithKey((_, v1) -> f(v1), k, m)////// Updates `m` with `k => v1` if `k => v` is in `m` and `f(k, v) = Some(v1)`. Otherwise, returns `m`.////// Purity reflective: Applies `f` lazily if `f` is pure.///@Experimental@LazyWhenPurepubdefupdateWithKey(f: (k, v) -> Option[v] \ ef, k: k, m: DelayMap[k, v]): DelayMap[k, v] \ efwithOrder[k] =matchpurityOf2(f) {case Purity2.Pure(g) => updateWithKeyL(g, k, m)case Purity2.Impure(g) => updateWithKeyE(g, k, m) }////// Helper function for `updateWithKey`. Does not force the `v`.///@LazydefupdateWithKeyL(f: (k, v) -> Option[v], k: k, m: DelayMap[k, v]): DelayMap[k, v] withOrder[k] =let DMap(t) = m;letf1 = (k1, v1) -> {letres = lazymatchf(k1, forcev1) {case Some(v2) => v2case None => forcev1 }; Some(res) }; DMap(RedBlackTree.updateWith(f1, k, t))////// Helper function for `updateWithKey`. Forces `v`.///defupdateWithKeyE(f: (k, v) -> Option[v] \ ef, k: k, m: DelayMap[k, v]): DelayMap[k, v] \ efwithOrder[k] =let DMap(t) = m;letf1 = (k1, v1) -> {letres = f(k1, forcev1);matchres {case Some(v2) => Some(lazyv2)case None => None } }; DMap(RedBlackTree.updateWith(f1, k, t))////// Returns the map `m` as a list of key-value pairs.///@ExperimentalpubdeftoList(m: DelayMap[k, v]): List[(k, v)] =foldRightWithKey((k, v, acc) -> (k, v) :: acc, Nil, m)////// Returns `m` as a Map, i.e. every value is forced.///@Experimental@ParallelpubdeftoMap(m: DelayMap[k, v]): Map[k, v] =let_ = parallelForce(m);let DMap(t) = m; Map.Map(RedBlackTree.mapWithKey((_, v) -> forcev, t))////// Returns the map `m` as a set of key-value pairs.///@ExperimentalpubdeftoSet(m: DelayMap[k, v]): Set[(k, v)] withOrder[k], Order[v] =foldLeftWithKey((acc, k, v) -> Set.insert((k, v), acc), Set.empty(), m)////// Returns an iterator over all key-value pairs in `m`.///@Experimentalpubdefiterator(rc: Region[r], m: DelayMap[a, b]): Iterator[(a, b), r, r] \ r =let DMap(t) = m;RedBlackTree.iterator(rc, t) |> Iterator.map(match (k, v) -> (k, forcev))////// Applies `f` to every `(key, value)` of `m`.///@ExperimentalpubdefforEach(f: (k, v) -> Unit \ ef, m: DelayMap[k, v]): Unit \ ef =let_ = parallelForce(m);let DMap(t) = m;letf1 = (k, v) -> f(k, forcev);RedBlackTree.forEach(f1, t)////// Applies `f` to tuple `(index, key, value)` formed of the keys and values of/// DelayMap `m` and the index of the traversal.///@ExperimentalpubdefforEachWithIndex(f: (Int32, k, v) -> Unit \ ef, m: DelayMap[k, v]): Unit \ ef = regionrc {letix = Ref.fresh(rc, 0);letf1 = (k, v) -> { leti = Ref.get(ix); f(i, k, v); Ref.put(i+1, ix) };forEach(f1, m) }////// Returns the sum of all values in `m`.///@Experimental@ParallelpubdefsumKeys(m: DelayMap[Int32, v]): Int32 =sumWith((k, _) -> k, m)////// Returns the sum of all values in `m`.///@Experimental@ParallelpubdefsumValues(m: DelayMap[k, Int32]): Int32 =sumWith((_, v) -> v, m)////// Returns the sum of all key-value pairs `k => v` in `m`/// according to the function `f`.////// Purity reflective: Runs in parallel when given a pure function `f`.///@Experimental@ParallelWhenPurepubdefsumWith(f: (k, v) -> Int32 \ ef, m: DelayMap[k, v]): Int32 \ ef =let DMap(t) = m;defsw() = {let_ = parallelForce(m);RedBlackTree.sumWith((k, v) -> f(k, forcev), t) };matchpurityOf2(f) {case Purity2.Pure(g) =>if (useParallelEvaluation(m))leth = (k, v) -> g(k, forcev);RedBlackTree.parSumWith(h, t)elsesw()case Purity2.Impure(_) => sw() }////// Returns the concatenation of the string representation of each key `k`/// in `m` with `sep` inserted between each element.///@ExperimentalpubdefjoinKeys(sep: String, m: DelayMap[k, v]): StringwithToString[k] =let DMap(t) = m;RedBlackTree.joinKeys(sep, t)////// Returns the concatenation of the string representation of each value `v`/// in `m` with `sep` inserted between each element.///@ExperimentalpubdefjoinValues(sep: String, m: DelayMap[k, v]): StringwithToString[v] =joinWith((_, v) -> ToString.toString(v), sep, m)////// Returns the concatenation of the string representation of each key-value pair/// `k => v` in `m` according to `f` with `sep` inserted between each element.///@ExperimentalpubdefjoinWith(f: (k, v) -> String \ ef, sep: String, m: DelayMap[k, v]): String \ ef =let_ = parallelForce(m);let DMap(t) = m;RedBlackTree.joinWith((k, v) -> f(k, forcev), sep, t)}