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_scott_utils/list as scott_list
fn avg_of_sums_and_products(xs: List<Int>) -> Int {
let
sum,
product,
<-
scott_list.foldr2(
xs,
0,
1,
fn(x, sum_so_far, prod_so_far, return) {
return(sum_so_far + x, prod_so_far * x)
},
)
(sum + product) / 2
}
The same code without backpassing syntactic sugar:
use aiken_scott_utils/list as scott_list
fn avg_of_sums_and_products_desugared(xs: List<Int>) -> Int {
scott_list.foldr2(
xs,
0,
1,
fn(x, sum_so_far, prod_so_far, return) {
return(sum_so_far + x, prod_so_far * x)
},
fn(sum, product) { (sum + product) / 2 }
)
}
foldl2(
self: List<x>,
zero_a: a,
zero_b: b,
with: fn(x, a, b, Scott2<a, b, result>) -> result,
return: Scott2<a, b, result>,
) -> result
foldr2(
self: List<x>,
zero_a: a,
zero_b: b,
with: fn(x, a, b, Scott2<a, b, result>) -> result,
return: Scott2<a, b, result>,
) -> result
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