Skip to content

Commit

Permalink
Handle stringly keyed maps!
Browse files Browse the repository at this point in the history
  • Loading branch information
Austin Erlandson committed May 19, 2020
1 parent f6b91d6 commit 1904c8e
Showing 1 changed file with 35 additions and 4 deletions.
39 changes: 35 additions & 4 deletions lib/destructure.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@ defmodule Destructure do
"""

@doc """
Easy destructuring of `map`, `structs`, and `keyword`, with atom keys only.
String keys are not supported because Elixir raises a `SyntaxError` on syntax
like `%{"name"}`. Optional key also need to be placed at the last for the same
reason with the string key.
Easy destructuring of `map`, `structs`, `keyword`, with atom keys.
String keys are supported via a special syntax `d(s%{param})`.
## Examples
Expand Down Expand Up @@ -43,6 +41,25 @@ defmodule Destructure do
...> {first, last, mail}
{"Daniel", "Berkompas", "top@secret.com"}
For Maps with String Keys:
iex> d(s%{name}) = %{"name" => "Daniel Berkompas"}
...> name
"Daniel Berkompas"
With multiple keys:
iex> d(s%{name, email}) = %{"name" => "Daniel Berkompas", "email" => "top@secret.com"}
...> {name, email}
{"Daniel Berkompas", "top@secret.com"}
With multiple keys and custom variable naming:
iex> d(s%{name, "email" => mail}) = %{"name" => "Daniel Berkompas", "email" => "top@secret.com"}
...> {name, mail}
{"Daniel Berkompas", "top@secret.com"}
For structs:
iex> d(%Person{name}) = %Person{name: "Daniel Berkompas"}
Expand Down Expand Up @@ -96,6 +113,12 @@ defmodule Destructure do
{:%{}, context, Enum.map(args, &pattern/1)}
end

# Handle string maps, including ones with multiple keys
# {:s, [], [{:%{}, [], [{:stuff, [], Elixir}, {:things, [], Elixir}]}]}
defmacro d({:s, _, [{:%{}, context, args}]}) do
{:%{}, context, Enum.map(args, &s_pattern/1)}
end

# Handle structs, including ones with multiple keys
# {:%, [],
# [{:__aliases__, [alias: false], [:Namespace]},
Expand All @@ -121,12 +144,20 @@ defmodule Destructure do
Enum.map(list, &pattern/1)
end

defp s_pattern({key, _, _} = variable) do
{key |> Atom.to_string(), variable}
end

defp s_pattern(otherwise), do: pattern(otherwise)

defp pattern({key, _, _} = variable) do
{key, variable}
end

defp pattern([arg]) do
arg
end

defp pattern(other) do
other
end
Expand Down

0 comments on commit 1904c8e

Please sign in to comment.