Current section
Files
Jump to
Current section
Files
src/metamon@transform@list.erl
-module(metamon@transform@list).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/metamon/transform/list.gleam").
-export([reverse/0, dedupe/0, prepend/1, append/1, shuffle/1]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(
" Standard `Transform(List(a))` constructors used in metamorphic\n"
" relations. Each transform is named and deterministic.\n"
).
-file("src/metamon/transform/list.gleam", 10).
?DOC(" Reverse the list.\n").
-spec reverse() -> metamon@transform:transform(list(any())).
reverse() ->
metamon@transform:new(<<"list.reverse"/utf8>>, fun lists:reverse/1).
-file("src/metamon/transform/list.gleam", 23).
-spec loop_dedupe(list(HSY), list(HSY), list(HSY)) -> list(HSY).
loop_dedupe(Items, Seen, Acc) ->
case Items of
[] ->
lists:reverse(Acc);
[First | Rest] ->
case gleam@list:contains(Seen, First) of
true ->
loop_dedupe(Rest, Seen, Acc);
false ->
loop_dedupe(Rest, [First | Seen], [First | Acc])
end
end.
-file("src/metamon/transform/list.gleam", 19).
-spec dedupe_keep_first(list(HSV)) -> list(HSV).
dedupe_keep_first(Items) ->
loop_dedupe(Items, [], []).
-file("src/metamon/transform/list.gleam", 15).
?DOC(" Drop duplicates, keeping the first occurrence of each element.\n").
-spec dedupe() -> metamon@transform:transform(list(any())).
dedupe() ->
metamon@transform:new(<<"list.dedupe"/utf8>>, fun dedupe_keep_first/1).
-file("src/metamon/transform/list.gleam", 35).
?DOC(" Prepend `value` to the list.\n").
-spec prepend(HTD) -> metamon@transform:transform(list(HTD)).
prepend(Value) ->
metamon@transform:new(
<<"list.prepend"/utf8>>,
fun(Items) -> [Value | Items] end
).
-file("src/metamon/transform/list.gleam", 40).
?DOC(" Append `value` to the list.\n").
-spec append(HTG) -> metamon@transform:transform(list(HTG)).
append(Value) ->
metamon@transform:new(
<<"list.append"/utf8>>,
fun(Items) -> lists:append(Items, [Value]) end
).
-file("src/metamon/transform/list.gleam", 62).
-spec assign_keys_and_sort(list(HTP), metamon@generator@seed:seed(), integer()) -> list(HTP).
assign_keys_and_sort(Items, S, Length) ->
Keyed = gleam@list:fold(
Items,
{S, []},
fun(Acc, Value) ->
{State, Keyed_acc} = Acc,
{Key, Next_state} = metamon@generator@seed:next_int_in(
State,
0,
Length * 100
),
{Next_state, [{Key, Value} | Keyed_acc]}
end
),
{_, With_keys} = Keyed,
_pipe = With_keys,
_pipe@1 = gleam@list:sort(
_pipe,
fun(Left, Right) ->
gleam@int:compare(erlang:element(1, Left), erlang:element(1, Right))
end
),
gleam@list:map(_pipe@1, fun(Pair) -> erlang:element(2, Pair) end).
-file("src/metamon/transform/list.gleam", 54).
-spec shuffle_with(list(HTM), metamon@generator@seed:seed()) -> list(HTM).
shuffle_with(Items, S) ->
Length = erlang:length(Items),
case Length =< 1 of
true ->
Items;
false ->
assign_keys_and_sort(Items, S, Length)
end.
-file("src/metamon/transform/list.gleam", 48).
?DOC(
" A deterministic shuffle parametrised by a seed integer. The same\n"
" integer always produces the same permutation. Implemented as a\n"
" stable sort by random keys (Knuth's \"decorate, sort, undecorate\"\n"
" pattern).\n"
).
-spec shuffle(integer()) -> metamon@transform:transform(list(any())).
shuffle(Seed_value) ->
metamon@transform:new(
<<<<"list.shuffle("/utf8,
(erlang:integer_to_binary(Seed_value))/binary>>/binary,
")"/utf8>>,
fun(Items) ->
shuffle_with(Items, metamon@generator@seed:seed(Seed_value))
end
).