Skip to content

Commit 227ed06

Browse files
committedMar 1, 2025
document union_with, insert_with and flatten_with changes.
1 parent 4618aed commit 227ed06

File tree

5 files changed

+80
-28
lines changed

5 files changed

+80
-28
lines changed
 

‎CHANGELOG.md

+16
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
11
# Changelog
22

3+
## v3.0.0 - UNRELEASED
4+
5+
### Added
6+
7+
- [`aiken/collection/list.{foldl2}`](https://aiken-lang.github.io/stdlib/aiken/collection/list.html#foldl2): to left-fold over lists while accumulating two separate results. This is reasonably faster than constructing a list of pairs.
8+
9+
- [`aiken/collection/list.{foldr2}`](https://aiken-lang.github.io/stdlib/aiken/collection/list.html#foldr2): to right-fold over lists while accumulating two separate results. This is reasonably faster than constructing a list of pairs.
10+
11+
### Changed
12+
13+
- <sup>⚠️ BREAKING-CHANGE ⚠️</sup> [`aiken/collection/dict.{insert_with}`](https://aiken-lang.github.io/stdlib/aiken/collection/dict.html#insert_with), [`aiken/collection/dict.{union_with}`](https://aiken-lang.github.io/stdlib/aiken/collection/dict.html#union_with) and [`cardano/assets.{flatten_with}`](https://aiken-lang.github.io/stdlib/cardano/assets.html#flatten_with) have a reworked API using two callbacks instead of a single callback returning `Option`. These gives them better performances, alongside a few other functions using them internally. To ease the construction of the callbacks, new modules with callback strategies have been created:
14+
- [`aiken/collection/dict/strategy`](https://aiken-lang.github.io/stdlib/aiken/collection/dict/strategy.html)
15+
- [`cardano/assets/strategy`](https://aiken-lang.github.io/stdlib/cardano/assets/strategy.html)
16+
17+
18+
319
## v2.2.0 - 2024-12-13
420

521
### Added

‎lib/aiken/collection/dict.ak

+11-11
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
//// > [`dict.from_ascending_list`](#from_ascending_list).
1414

1515
use aiken/builtin
16-
use aiken/collection/dict/union.{UnionStrategy}
16+
use aiken/collection/dict/strategy.{UnionStrategy}
1717

1818
/// An opaque `Dict`. The type is opaque because the module maintains some
1919
/// invariant, namely: there's only one occurrence of a given key in the dictionary.
@@ -162,7 +162,7 @@ fn do_from_pairs(xs: Pairs<ByteArray, value>) -> Pairs<ByteArray, value> {
162162
when xs is {
163163
[] -> []
164164
[Pair(k, v), ..rest] ->
165-
do_insert_with(do_from_pairs(rest), k, v, union.keep_left())
165+
do_insert_with(do_from_pairs(rest), k, v, strategy.keep_left())
166166
}
167167
}
168168

@@ -734,9 +734,9 @@ test insert_2() {
734734
///
735735
/// let result =
736736
/// dict.empty
737-
/// |> dict.insert_with(key: "a", value: 1, with: union.sum())
738-
/// |> dict.insert_with(key: "b", value: 2, with: union.sum())
739-
/// |> dict.insert_with(key: "a", value: 3, with: union.sum())
737+
/// |> dict.insert_with(key: "a", value: 1, with: strategy.sum())
738+
/// |> dict.insert_with(key: "b", value: 2, with: strategy.sum())
739+
/// |> dict.insert_with(key: "a", value: 3, with: strategy.sum())
740740
/// |> dict.to_pairs()
741741
///
742742
/// result == [Pair("a", 4), Pair("b", 2)]
@@ -760,8 +760,8 @@ pub fn insert_with(
760760
test insert_with_1() {
761761
let result =
762762
empty
763-
|> insert_with(key: "foo", value: 1, with: union.sum())
764-
|> insert_with(key: "bar", value: 2, with: union.sum())
763+
|> insert_with(key: "foo", value: 1, with: strategy.sum())
764+
|> insert_with(key: "bar", value: 2, with: strategy.sum())
765765
|> to_pairs()
766766

767767
result == [Pair("bar", 2), Pair("foo", 1)]
@@ -770,9 +770,9 @@ test insert_with_1() {
770770
test insert_with_2() {
771771
let result =
772772
empty
773-
|> insert_with(key: "foo", value: 1, with: union.sum())
774-
|> insert_with(key: "bar", value: 2, with: union.sum())
775-
|> insert_with(key: "foo", value: 3, with: union.sum())
773+
|> insert_with(key: "foo", value: 1, with: strategy.sum())
774+
|> insert_with(key: "bar", value: 2, with: strategy.sum())
775+
|> insert_with(key: "foo", value: 3, with: strategy.sum())
776776
|> to_pairs()
777777

778778
result == [Pair("bar", 2), Pair("foo", 4)]
@@ -1065,7 +1065,7 @@ test union_with_1() {
10651065
|> insert(bar, 42)
10661066
|> insert(foo, 1337)
10671067

1068-
let result = union_with(left, right, with: union.sum())
1068+
let result = union_with(left, right, with: strategy.sum())
10691069

10701070
result == from_pairs([Pair(foo, 1351), Pair(bar, 42)])
10711071
}

‎lib/aiken/collection/dict/union.ak ‎lib/aiken/collection/dict/strategy.ak

+34-3
Original file line numberDiff line numberDiff line change
@@ -11,30 +11,61 @@ pub type KeepValue<key, value> =
1111
pub type DiscardValue<key, value> =
1212
fn() -> Pairs<key, value>
1313

14+
// ### Union Strategies
15+
1416
/// A strategy which always fail, enforcing the dict contains no duplicate.
17+
///
18+
/// ```aiken
19+
/// fn(_, _, _, _, _) {
20+
/// fail @"unexpected duplicate key found in dict."
21+
/// }
22+
/// ```
1523
pub fn expect_no_duplicate() -> UnionStrategy<key, value> {
1624
fn(_, _, _, _, _) {
1725
fail @"unexpected duplicate key found in dict."
1826
}
1927
}
2028

2129
/// Combine values by keeping the values present in the left-most dict.
30+
///
31+
/// ```aiken
32+
/// fn(_key, left, _right, keep, _discard) { keep(left) }
33+
/// ```
2234
pub fn keep_left() -> UnionStrategy<key, value> {
2335
fn(_key, left, _right, keep, _discard) { keep(left) }
2436
}
2537

26-
/// Combine values by keeping the values present in the left-most dict.
38+
/// Combine values by keeping the values present in the right-most dict.
39+
///
40+
/// ```aiken
41+
/// fn(_key, _left, right, keep, _discard) { keep(right) }
42+
/// ```
2743
pub fn keep_right() -> UnionStrategy<key, value> {
2844
fn(_key, _left, right, keep, _discard) { keep(right) }
2945
}
3046

3147
/// Combine values by taking their sum.
48+
///
49+
/// ```aiken
50+
/// fn(_key, left, right, keep, _discard) { keep(left + right) }
51+
/// ```
3252
pub fn sum() -> UnionStrategy<key, Int> {
3353
fn(_key, left, right, keep, _discard) { keep(left + right) }
3454
}
3555

36-
/// Combine values by taking their sum, only if it is non-null. Otherwise,
37-
/// discard the key/value entirely.
56+
/// Combine values by taking their sum, only if it is non-null. If the
57+
/// resulting sum is 0, discard the key/value entirely.
58+
///
59+
/// ```aiken
60+
/// fn(_key, left, right, keep, discard) {
61+
/// let value = left + right
62+
/// if value == 0 {
63+
/// discard()
64+
/// } else {
65+
/// keep(value)
66+
/// }
67+
/// }
68+
/// ```
3869
pub fn sum_if_non_zero() -> UnionStrategy<key, Int> {
3970
fn(_key, left, right, keep, discard) {
4071
let value = left + right

‎lib/cardano/assets.ak

+7-10
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use aiken/builtin
22
use aiken/collection/dict.{Dict, from_ascending_pairs_with}
3-
use aiken/collection/dict/union as dict_union
3+
use aiken/collection/dict/strategy as dict_strategy
44
use aiken/collection/list
55
use aiken/crypto.{Blake2b_224, Hash, Script}
66
use aiken/option
7-
use cardano/assets/union
7+
use cardano/assets/strategy.{FlattenStrategy}
88

99
/// Lovelace is now a type wrapper for Int.
1010
pub type Lovelace =
@@ -79,7 +79,7 @@ pub fn from_asset_list(xs: Pairs<PolicyId, Pairs<AssetName, Int>>) -> Value {
7979
expect Pair(p, [_, ..] as x) = inner
8080
x
8181
|> from_ascending_pairs_with(fn(v) { v != 0 })
82-
|> dict.insert_with(acc, p, _, dict_union.expect_no_duplicate())
82+
|> dict.insert_with(acc, p, _, dict_strategy.expect_no_duplicate())
8383
},
8484
)
8585
|> Value
@@ -556,7 +556,7 @@ pub fn add(
556556
left,
557557
asset_name,
558558
quantity,
559-
dict_union.sum_if_non_zero(),
559+
dict_strategy.sum_if_non_zero(),
560560
)
561561

562562
if dict.is_empty(inner_result) {
@@ -623,7 +623,7 @@ pub fn merge(left v0: Value, right v1: Value) -> Value {
623623
v0.inner,
624624
v1.inner,
625625
fn(_, a0, a1, keep, discard) {
626-
let result = dict.union_with(a0, a1, dict_union.sum_if_non_zero())
626+
let result = dict.union_with(a0, a1, dict_strategy.sum_if_non_zero())
627627
if dict.is_empty(result) {
628628
discard()
629629
} else {
@@ -793,10 +793,7 @@ pub fn flatten(self: Value) -> List<(PolicyId, AssetName, Int)> {
793793
/// Flatten a `Value` as a list of results, possibly discarding some along the way.
794794
///
795795
/// When the transform function returns `None`, the result is discarded altogether.
796-
pub fn flatten_with(
797-
self: Value,
798-
with: union.UnionStrategy<result>,
799-
) -> List<result> {
796+
pub fn flatten_with(self: Value, with: FlattenStrategy<result>) -> List<result> {
800797
dict.foldr(
801798
self.inner,
802799
[],
@@ -819,7 +816,7 @@ pub fn flatten_with(
819816
}
820817

821818
test flatten_with_1() {
822-
flatten_with(zero, union.triple()) == []
819+
flatten_with(zero, strategy.triple()) == []
823820
}
824821

825822
test flatten_with_2() {

‎lib/cardano/assets/union.ak ‎lib/cardano/assets/strategy.ak

+12-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use aiken/crypto.{Blake2b_224, Hash, Script}
22

3-
/// A strategy for combining two values in a dictionnary that belong to the same key.
4-
pub type UnionStrategy<result> =
3+
/// A strategy for flattening an asset list.
4+
pub type FlattenStrategy<result> =
55
fn(
66
Hash<Blake2b_224, Script>,
77
ByteArray,
@@ -19,8 +19,16 @@ pub type KeepResult<result> =
1919
pub type DiscardResult<result> =
2020
fn() -> List<result>
2121

22-
/// Combine values by keeping them in a 3-tuple.
23-
pub fn triple() -> UnionStrategy<(Hash<Blake2b_224, Script>, ByteArray, Int)> {
22+
// ### Flatten strategies
23+
24+
/// Keep all assets, combining them as a 3-tuple.
25+
///
26+
/// ```aiken
27+
/// fn(policy_id, asset_name, quantity, keep, _discard) {
28+
/// keep((policy_id, asset_name, quantity))
29+
/// }
30+
/// ```
31+
pub fn triple() -> FlattenStrategy<(Hash<Blake2b_224, Script>, ByteArray, Int)> {
2432
fn(policy_id, asset_name, quantity, keep, _discard) {
2533
keep((policy_id, asset_name, quantity))
2634
}

0 commit comments

Comments
 (0)
Please sign in to comment.