Packages

An easy to use and pipe friendly way to have named arugments

Current section

Files

Jump to
argument_names lib argument_names.ex
Raw

lib/argument_names.ex

defmodule ArgumentNames do
@moduledoc """
Documentation for `ArgumentNames`.
"""
@doc """
Defines a public function with named arguments
## Examples
defmodule Foo do
require ArgumentNames
import ArgumentNames
defnamed div(first, second) do
first / second
end
end
Foo.div(2, 4)
#=> 0.5
Foo.div(second ~> 4, 2)
#=> 0.5
"""
defmacro defnamed({name, meta, args} = call, do: expr) do
name_and_args = {:"call_#{name}", meta, args}
outer_args = Macro.escape(args)
quote do
@doc false
def unquote(name_and_args) do
unquote(expr)
end
defmacro unquote(call) do
ArgumentNames.do_call_function(unquote(outer_args), unquote(args), unquote(name), __MODULE__)
end
end
end
@doc """
Defines a private function with named arguments
## Examples
defmodule Foo do
require ArgumentNames
import ArgumentNames
defnamedp div(first, second) do
first / second
end
end
"""
defmacro defnamedp({name, meta, args} = call, do: expr) do
name_and_args = {:"call_#{name}", meta, args}
outer_args = Macro.escape(args)
quote do
@doc false
defp unquote(name_and_args) do
unquote(expr)
end
defmacrop unquote(call) do
ArgumentNames.do_call_function(unquote(outer_args), unquote(args), unquote(name), __MODULE__)
end
end
end
@doc false
def do_call_function(outer_args, args, name, mod) do
split_args =
args
|> Enum.group_by(fn
{:~>, _, _} -> true
_ -> false
end)
arr =
List.foldl(split_args[true] || [], :array.new(length(args)), fn
{:~>, _, [{var_name, _, _}, val]}, acc ->
idx =
Enum.find_index(outer_args, fn {outer_name, _, _} ->
var_name == outer_name
end)
:array.set(idx, val, acc)
end)
arr =
List.foldl(split_args[false] || [], arr, fn
val, acc ->
set_array(0, acc, val)
end)
{{:., [], [
{:__aliases__, [alias: false], [mod]},
:"call_#{name}"
]}, [], :array.to_list(arr)}
end
@doc false
def set_array(idx, array, val) do
if :array.get(idx, array) == :undefined do
:array.set(idx, val, array)
else
set_array(idx + 1, array, val)
end
end
end