Utility functions for traversing lists while collecting more than one
values.
Sample code to see how you can use one of the fold functions with the
backpassing syntax:
use aiken/math.{pow}
use aiken_scott_utils/list as scott_list
fn avg_of_sums_products_powers(xs: List<Int>) -> Int {
let
sum,
product,
power
<-
scott_list.foldr3(
xs,
0,
1,
1,
fn(x, sum_so_far, prod_so_far, pow_so_far, return) {
return(sum_so_far + x, prod_so_far * x, pow(x, pow_so_far))
},
)
(sum + product + power) / 3
}
The same code without backpassing syntactic sugar:
use aiken/math.{pow}
use aiken_scott_utils/list as scott_list
fn avg_of_sums_and_products_desugared(xs: List<Int>) -> Int {
scott_list.foldr3(
xs,
0,
1,
1,
fn(x, sum_so_far, prod_so_far, pow_so_far, return) {
return(sum_so_far + x, prod_so_far * x, pow(x, pow_so_far))
},
fn(sum, product, power) { (sum + product + power) / 3 }
)
}
foldl3(
self: List<x>,
zero_a: a,
zero_b: b,
zero_c: c,
with: fn(x, a, b, c, Scott3<a, b, c, result>) -> result,
return: Scott3<a, b, c, result>,
) -> result
foldr3(
self: List<x>,
zero_a: a,
zero_b: b,
zero_c: c,
with: fn(x, a, b, c, Scott3<a, b, c, result>) -> result,
return: Scott3<a, b, c, result>,
) -> result
foldl4(
self: List<x>,
zero_a: a,
zero_b: b,
zero_c: c,
zero_d: d,
with: fn(x, a, b, c, d, Scott4<a, b, c, d, result>) -> result,
return: Scott4<a, b, c, d, result>,
) -> result
foldr4(
self: List<x>,
zero_a: a,
zero_b: b,
zero_c: c,
zero_d: d,
with: fn(x, a, b, c, d, Scott4<a, b, c, d, result>) -> result,
return: Scott4<a, b, c, d, result>,
) -> result
foldl5(
self: List<x>,
zero_a: a,
zero_b: b,
zero_c: c,
zero_d: d,
zero_e: e,
with: fn(x, a, b, c, d, e, Scott5<a, b, c, d, e, result>) -> result,
return: Scott5<a, b, c, d, e, result>,
) -> result
foldr5(
self: List<x>,
zero_a: a,
zero_b: b,
zero_c: c,
zero_d: d,
zero_e: e,
with: fn(x, a, b, c, d, e, Scott5<a, b, c, d, e, result>) -> result,
return: Scott5<a, b, c, d, e, result>,
) -> result
foldl6(
self: List<x>,
zero_a: a,
zero_b: b,
zero_c: c,
zero_d: d,
zero_e: e,
zero_f: f,
with: fn(x, a, b, c, d, e, f, Scott6<a, b, c, d, e, f, result>) -> result,
return: Scott6<a, b, c, d, e, f, result>,
) -> result
foldr6(
self: List<x>,
zero_a: a,
zero_b: b,
zero_c: c,
zero_d: d,
zero_e: e,
zero_f: f,
with: fn(x, a, b, c, d, e, f, Scott6<a, b, c, d, e, f, result>) -> result,
return: Scott6<a, b, c, d, e, f, result>,
) -> result
find2(
self: List<x>,
predicate_a: fn(x) -> Bool,
predicate_b: fn(x) -> Bool,
return: Scott2<Option<x>, Option<x>, result>,
) -> result
find3(
self: List<x>,
predicate_a: fn(x) -> Bool,
predicate_b: fn(x) -> Bool,
predicate_c: fn(x) -> Bool,
return: Scott3<Option<x>, Option<x>, Option<x>, result>,
) -> result
find4(
self: List<x>,
predicate_a: fn(x) -> Bool,
predicate_b: fn(x) -> Bool,
predicate_c: fn(x) -> Bool,
predicate_d: fn(x) -> Bool,
return: Scott4<Option<x>, Option<x>, Option<x>, Option<x>, result>,
) -> result
find5(
self: List<x>,
predicate_a: fn(x) -> Bool,
predicate_b: fn(x) -> Bool,
predicate_c: fn(x) -> Bool,
predicate_d: fn(x) -> Bool,
predicate_e: fn(x) -> Bool,
return: Scott5<Option<x>, Option<x>, Option<x>, Option<x>, Option<x>, result>,
) -> result
find6(
self: List<x>,
predicate_a: fn(x) -> Bool,
predicate_b: fn(x) -> Bool,
predicate_c: fn(x) -> Bool,
predicate_d: fn(x) -> Bool,
predicate_e: fn(x) -> Bool,
predicate_f: fn(x) -> Bool,
return: Scott6<
Option<x>,
Option<x>,
Option<x>,
Option<x>,
Option<x>,
Option<x>,
result,
>,
) -> result
at2(
self: List<x>,
index_a: Int,
index_b: Int,
return: Scott2<Option<x>, Option<x>, result>,
) -> result
Unit tests suggest using at2 is not very different from using list.at
twice.
at3(
self: List<x>,
index_a: Int,
index_b: Int,
index_c: Int,
return: Scott3<Option<x>, Option<x>, Option<x>, result>,
) -> result
Unit tests suggest using at3 is not very different from using list.at
three times.
at4(
self: List<x>,
index_a: Int,
index_b: Int,
index_c: Int,
index_d: Int,
return: Scott4<Option<x>, Option<x>, Option<x>, Option<x>, result>,
) -> result
at4 and up are more performant than multiple calls to list.at.
at5(
self: List<x>,
index_a: Int,
index_b: Int,
index_c: Int,
index_d: Int,
index_e: Int,
return: Scott5<Option<x>, Option<x>, Option<x>, Option<x>, Option<x>, result>,
) -> result
at6(
self: List<x>,
index_a: Int,
index_b: Int,
index_c: Int,
index_d: Int,
index_e: Int,
index_f: Int,
return: Scott6<
Option<x>,
Option<x>,
Option<x>,
Option<x>,
Option<x>,
Option<x>,
result,
>,
) -> result