Skip to content

Commit

Permalink
Merge pull request danielberkompas#3 from muhifauzan/struct-support
Browse files Browse the repository at this point in the history
Add destructure structs feature
  • Loading branch information
danielberkompas authored Dec 12, 2016
2 parents 0326b39 + 6290bbb commit ab353d0
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 7 deletions.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ def full_name(d%{first_name, last_name}) do
end
```

Or with structs:
```elixir
import Destructure

def full_name(d%Person{first_name, last_name}) do
"#{first_name} #{last_name}"
end
```

It also works in case statements, like this:

```elixir
Expand Down
38 changes: 32 additions & 6 deletions lib/destructure.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ defmodule Destructure do
"""

@doc """
Easy destructuring of maps and keyword lists, with atom keys only. String keys
are not supported because Elixir raises a `SyntaxError` on syntax like
`%{"name"}`.
Easy destructuring of maps, structs, and keyword lists, 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.
## Examples
Expand All @@ -20,8 +21,7 @@ defmodule Destructure do
Or in case/for/with statements.
iex> case %{name: "Mike"} do
...> d%{name} ->
...> name
...> d%{name} -> name
...> end
"Mike"
Expand All @@ -43,6 +43,24 @@ defmodule Destructure do
...> {first, last, mail}
{"Daniel", "Berkompas", "top@secret.com"}
For structs:
iex> d(%Person{name}) = %Person{name: "Daniel Berkompas"}
...> name
"Daniel Berkompas"
With multiple keys:
iex> d(%Person{name, email}) = %Person{name: "Daniel Berkompas", email: "top@secret.com"}
...> {name, email}
{"Daniel Berkompas", "top@secret.com"}
With multiple keys and custom variable naming:
iex> d(%Person{name, email: mail}) = %Person{name: "Daniel Berkompas", email: "top@secret.com"}
...> {name, mail}
{"Daniel Berkompas", "top@secret.com"}
For keyword lists:
iex> d({name}) = [name: "Daniel"]
Expand Down Expand Up @@ -78,8 +96,16 @@ defmodule Destructure do
{:%{}, context, Enum.map(args, &pattern/1)}
end

# Handle structs, including ones with multiple keys
# {:%, [],
# [{:__aliases__, [alias: false], [:Namespace]},
# {:%{}, [], [{:first, [], Elixir}, {:second, [], Elixir}]}]}
defmacro d({:%, _, [{:__aliases__, _, _}, {:%{}, context, args}]}) do
{:%{}, context, Enum.map(args, &pattern/1)}
end

# Handle 1 and 3+ element tuples
# {:{}, [], [{:variable_name, [], Elixir}]}
# {:{}, [], [{:first, [], Elixir}]}
defmacro d({:{}, _, args}) do
Enum.map(args, &pattern/1)
end
Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ defmodule Destructure.Mixfile do

def project do
[app: :destructure,
version: "0.1.1",
version: "0.2.0",
elixir: "~> 1.3",
build_embedded: Mix.env == :prod,
start_permanent: Mix.env == :prod,
Expand Down
6 changes: 6 additions & 0 deletions test/destructure_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,11 @@ defmodule DestructureTest do

import Destructure

defmodule Person do
defstruct [:name, :email]
end

alias __MODULE__.Person

doctest Destructure
end

0 comments on commit ab353d0

Please sign in to comment.