Skip to content

Commit

Permalink
Define curried data constructor via Quark.Partial.defpartial
Browse files Browse the repository at this point in the history
`defpartial/2`   is   called    with   `args_without_defaults`   because
`defpartial/2` is  implemented using `defcurry/2` which  would pass args
with defaults to an anonymous function, but:

```elixir
== Compilation error in file lib/algae/tree/rose.ex ==
** (CompileError) lib/algae/tree/rose.ex:34: anonymous functions cannot have optional ar
guments
    (stdlib) lists.erl:1354: :lists.mapfoldl/3
    (elixir) src/elixir_fn.erl:19: :elixir_fn.expand/3
    lib/algae/tree/rose.ex:34: (module)
```

On the other hand,  it doesn't seem to be logical  to have defaults when
currying anyway:

```elixir
defmodule Person do
  defdata do
    name :: string
    age  :: integer
  end
end

Person.new_partial.("lofa")
```

I  would expect  the last  expression to  return a  function instead  of
`%Person{name: "lofa", age: 0}`.
  • Loading branch information
toraritte committed Mar 11, 2019
1 parent cd47031 commit 9cfab65
Showing 1 changed file with 20 additions and 1 deletion.
21 changes: 20 additions & 1 deletion lib/algae/internal.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,36 @@ defmodule Algae.Internal do
def data_ast(lines, %{aliases: _} = caller) when is_list(lines) do
{field_values, field_types, specs, args, defaults} = module_elements(lines, caller)

arg_count = Enum.count(args)

overridables =
Enum.map(0..arg_count, &({:new_partial, &1}))
++ [new: arg_count]
# More verbose, but clearer.
# for arity <- 0..Enum.count(args) do
# {:new, arity}
# end

args_without_defaults =
Enum.map(args, fn({:\\, [], [stripped, _]}) -> stripped end)

quote do
use Quark

@type t :: %__MODULE__{unquote_splicing(field_types)}
defstruct unquote(field_values)

defpartial new_partial(unquote_splicing(args_without_defaults)) do
struct(__MODULE__, unquote(defaults))
end

@doc "Positional constructor, with args in the same order as they were defined in"
@spec new(unquote_splicing(specs)) :: t()
def new(unquote_splicing(args)) do
struct(__MODULE__, unquote(defaults))
end

defoverridable [new: unquote(Enum.count(args))]
defoverridable unquote(overridables)
end
end

Expand Down

0 comments on commit 9cfab65

Please sign in to comment.