Current section
Files
Jump to
Current section
Files
lib/combinators/helper.ex
defmodule Formulae.Combinators.H do
@moduledoc false
def var(i), do: {:"i_#{i}", [], Elixir}
def idx(i), do: {:"idx_#{i}", [], Elixir}
def for_clause(i, l) do
{:<-, [],
[
{var(i), idx(i)},
{{:., [], [{:__aliases__, [alias: false], [:Enum]}, :with_index]}, [], [l]}
]}
end
### combinations
def sink_combination_clause(i) when i > 1 do
{:->, [],
[
[
{:when, [],
[
{{:_, [], Elixir}, idx(i)},
:ok,
{:<=, [context: Elixir, import: Kernel], [idx(i), idx(i - 1)]}
]}
],
{[], :ok}
]}
end
def sink_combination_clauses(i, body) when i > 1 do
Enum.reverse([
{:->, [], [[{var(i), idx(i)}, :ok], body]}
| Enum.map(2..i, &sink_combination_clause/1)
])
end
def sink_combination_clauses(1, body) do
[{:->, [], [[{var(1), idx(1)}, :ok], body]}]
end
def stream_combination_transform_clause(i, l, body) do
clauses = sink_combination_clauses(i, body)
{{{:., [], [{:__aliases__, [alias: false], [:Stream]}, :transform]}, [],
[
{{:., [], [{:__aliases__, [alias: false], [:Stream]}, :with_index]}, [], [l]},
:ok,
{:fn, [], clauses}
]}, :ok}
end
### permutations
def sink_permutation_clause(i),
do: {:->, [], [[{{:_, [], Elixir}, {:^, [], [idx(i)]}}, :ok], {[], :ok}]}
def sink_permutation_clauses(i, body) when i > 1 do
Enum.reverse([
{:->, [], [[{var(i), idx(i)}, :ok], body]}
| Enum.map((i - 1)..1//-1, &sink_permutation_clause/1)
])
end
def sink_permutation_clauses(1, body),
do: [{:->, [], [[{var(1), idx(1)}, :ok], body]}]
def stream_permutation_transform_clause(i, l, body) do
clauses = sink_permutation_clauses(i, body)
{{{:., [], [{:__aliases__, [alias: false], [:Stream]}, :transform]}, [],
[
{{:., [], [{:__aliases__, [alias: false], [:Stream]}, :with_index]}, [], [l]},
:ok,
{:fn, [], clauses}
]}, :ok}
end
### repeated permutations
def stream_transform_clause(i, l, body) do
{{{:., [], [{:__aliases__, [alias: false], [:Stream]}, :transform]}, [],
[
{{:., [], [{:__aliases__, [alias: false], [:Stream]}, :with_index]}, [], [l]},
:ok,
{:fn, [], [{:->, [], [[{var(i), idx(i)}, :ok], body]}]}
]}, :ok}
end
defmacro mapper(from, to, fun) when from <= to,
do: quote(do: Enum.map(unquote(from)..unquote(to), unquote(fun)))
defmacro mapper(from, to, fun),
do: quote(do: Enum.map(unquote(from)..unquote(to)//-1, unquote(fun)))
end