diff --git a/lib/aiken/collection/pairs.ak b/lib/aiken/collection/pairs.ak index a3aedb9..f3d6d5d 100644 --- a/lib/aiken/collection/pairs.ak +++ b/lib/aiken/collection/pairs.ak @@ -12,6 +12,7 @@ //// > and thus allow for duplicate keys. This is reflected in the functions used //// > to interact with them. +use aiken/builtin use aiken/primitive/bytearray // ## Inspecting @@ -572,6 +573,106 @@ test map_2() { map(fixture, with: fn(_, v) { v + 1 }) == [Pair("a", 2), Pair("b", 3)] } +/// Merge a value into the `Pairs` at a given key. If the key already exists, +/// its value is merged by the merging function. +/// +/// ```aiken +/// use aiken/builtin +/// use aiken/primitive/bytearray +/// +/// let compare_un_b_data = fn(l, r) { +/// bytearray.compare(l |> builtin.un_b_data, r |> builtin.un_b_data) +/// } +/// +/// let result = +/// [] +/// |> pairs.merge(key: "foo" |> builtin.b_data, value: 1, compare: compare_un_b_data, merging: builtin.add_integer) +/// |> pairs.merge(key: "bar" |> builtin.b_data, value: 2, compare: compare_un_b_data, merging: builtin.add_integer) +/// |> pairs.merge(key: "foo" |> builtin.b_data, value: 3, compare: compare_un_b_data, merging: builtin.add_integer) +/// +/// result == [Pair("bar" |> builtin.b_data, 2), Pair("foo" |> builtin.b_data, 4)] +/// ``` +/// +/// Notice that the key is of type `Data`. The function works with any key type, not just ByteArray. +/// Unlike `dict.from_pairs() |> dict.union_with() |> dict.to_pairs()` +pub fn merge( + self: Pairs, + key k: key, + value v: value, + compare: fn(key, key) -> Ordering, + merging: fn(value, value) -> value, +) -> Pairs { + when self is { + [] -> + [Pair(k, v)] + + [Pair(k2, v2), ..rest] -> + when compare(k, k2) is { + Less -> + [Pair(k, v), ..self] + + Equal -> + [Pair(k, merging(v, v2)), ..rest] + + Greater -> + [Pair(k2, v2), ..merge(rest, k, v, compare, merging)] + } + } +} + +test merge_1() { + let compare_un_b_data = + fn(l, r) { + bytearray.compare(l |> builtin.un_b_data, r |> builtin.un_b_data) + } + + let m = + [] + |> merge("foo" |> builtin.b_data, 42, compare_un_b_data, builtin.add_integer) + |> merge("foo" |> builtin.b_data, 14, compare_un_b_data, builtin.add_integer) + + m == [Pair("foo" |> builtin.b_data, 56)] +} + +test merge_2() { + let compare_un_b_data = + fn(l, r) { + bytearray.compare(l |> builtin.un_b_data, r |> builtin.un_b_data) + } + + let m = + [] + |> merge("foo" |> builtin.b_data, 42, compare_un_b_data, builtin.add_integer) + |> merge("bar" |> builtin.b_data, 14, compare_un_b_data, builtin.add_integer) + |> merge( + "baz" |> builtin.b_data, + 1337, + compare_un_b_data, + builtin.add_integer, + ) + + m == [ + Pair("bar" |> builtin.b_data, 14), + Pair("baz" |> builtin.b_data, 1337), + Pair("foo" |> builtin.b_data, 42), + ] +} + +test merge_3() { + let compare_un_b_data = + fn(l, r) { + bytearray.compare(l |> builtin.un_b_data, r |> builtin.un_b_data) + } + + let result = + [] + |> merge("foo" |> builtin.b_data, 1, compare_un_b_data, builtin.add_integer) + |> merge("bar" |> builtin.b_data, 2, compare_un_b_data, builtin.add_integer) + |> merge("foo" |> builtin.b_data, 3, compare_un_b_data, builtin.add_integer) + + result == [Pair("bar" |> builtin.b_data, 2), Pair("foo" |> builtin.b_data, 4)] +} + /// Insert a value in the `Pairs` at a given key. If the key already exists, /// its value is replaced. /// diff --git a/lib/cardano/transaction.ak b/lib/cardano/transaction.ak index 95d1197..6511a59 100644 --- a/lib/cardano/transaction.ak +++ b/lib/cardano/transaction.ak @@ -202,7 +202,7 @@ pub fn find_script_outputs( /// transaction.placeholder.id == /// #"0000000000000000000000000000000000000000000000000000000000000000" /// -/// transaction.placeholder.validity_range == interval.everything() +/// transaction.placeholder.validity_range == interval.everything /// ``` pub const placeholder: Transaction = Transaction {