Thanks Mike and Parker for the feedback so far.

Eric has proposed another approach, via module attributes:

@enforce [:name]

defstruct [:name, :age]


One of the benefits of using module attributes is that it matches nicely
the already supported @derive attribute:

@derive Poison.Encoder

@enforce [:name]

defstruct [:name, :age]


Furthermore, the module attribute composes better. For example, if we want
to support @enforce in defexception (which is based defstruct), we don't
need to change anything, it just works:

@enforce [:message]

defexception [:message]


The same could work with Ecto:

@enforce [:name]
schema "users" do
  ...
end


The only downside is that a module attribute can be silently defined. For
example, someone may set @enforce [:foo, :bar] in their module for other
reasons and now they will conflict. However, in such cases we can easily
check and guarantee all fields given to @enforce are also defined in the
struct.

Can anyone think of other pros-and-cons here?



*José Valim*
www.plataformatec.com.br
Skype: jv.ptec
Founder and Director of R&D

On Wed, May 25, 2016 at 4:33 PM, Parker Selbert <[email protected]> wrote:

> The most recent proposal, using `enforce: [:name]` is extremely clear, and
> nicely backward compatible. Overall I love the recent focus on enforcing
> the presence of attributes and data integrity.
>
> — Parker
>
>
> On Wed, May 25, 2016, at 02:10 AM, Mike Evans wrote:
>
> +1 as it solves the immediate clarity issue nicely with an undeniably
> strong word.
>
>
>
> On May 25, 2016, at 2:07 AM, José Valim <[email protected]>
> wrote:
>
> Given Peter's feedback, what if we define it as:
>
>
> defstruct [:name, :age], enforce: [:name]
>
>
> The idea of picking :enforce instead of :required is to avoid any possible
> confusion that some of those fields won't be effectively present in the
> struct.
>
> Thoughts?
>
>
>
>
> *José Valim*
>
> www.plataformatec.com.br
> Skype: jv.ptec
> Founder and Director of R&D
>
>
>
> On Wed, May 25, 2016 at 3:07 AM, eksperimental <
> [email protected]> wrote:
>
> José: great new feature. Definitely a needed one!
> and +1 on Peter Hamilton's suggestion on how to define required fields.
>
> An extra feature that will save us developers a lot of headeaches is
> the ability to define a list of accepted values per field. As as the
> current state, functions silently fail unexpected values are given
>
> On Tue, 24 May 2016 23:35:34 +0000
> Peter Hamilton <[email protected]> wrote:
>
> > I am not a fan of the proposed signature. Generally when we have
> > multiple clauses of different arity, we try to make them purely
> > extensions of the first. In the proposal, we go from (fields) to
> > (optional_fields, required_fields). While one could say that it's
> > really (optional_fields) to (optional_fields, required_fields), I
> > think that's changing the semantics of the current signature, which
> > to me is all the fields. I will submit, however, that this is a bit
> > subjective and realistically the same in practice.
> >
> > I would propose instead:
> >
> > defstruct [age: nil, name: nil], required: [:name]
> >
> > It not only maintains semantic backwards compatibility, but there
> > isn't an implicit meaning behind the two different arguments. It's
> > very clear that we have a list of arguments then an explicit list of
> > required fields.
> >
> > On Tue, May 24, 2016 at 4:26 PM José Valim
> > <[email protected]> wrote:
> >
> > > To clarify, both :age and :name fields will be present in the
> > > underlying User struct/map. The proposal is only about fields which
> > > must be enforced when building the structure.
> > >
> > > We will likely need better names than optional/required.
> > >
> > > *José Valim*
> > > www.plataformatec.com.br
> > > Skype: jv.ptec
> > > Founder and Director of R&D
> > >
> > > On Wed, May 25, 2016 at 1:17 AM, José Valim <
> > > [email protected]> wrote:
> > >
> > >> Hello everyone,
> > >>
> > >> I would like to propose an extension to defstruct that will require
> > >> certain fields to be given when expanding it. Here is an example:
> > >>
> > >> defmodule User do
> > >>
> > >>   defstruct [age: nil], # optional
> > >>
> > >>             [name: nil] # required
> > >>
> > >> end
> > >>
> > >>
> > >> With this feature, %User{} will fail as the :name field was not
> > >> specified. %User{name: "foo"} or %User{name: nil} will both work as
> > >> expected. The main use case is to make sure all important fields
> > >> are set when building the data. For example, we can use such
> > >> fields in the new date time types to enforce proper data
> > >> representation.
> > >>
> > >> *Extra notes*
> > >>
> > >> 1. The required fields are given as second argument to defstruct
> > >> as the API must remain backwards compatibility
> > >>
> > >> 2. The fields are required only when building structs. Matching
> > >> will always work without specifying any field, for example:
> > >> %User{} = user
> > >>
> > >> 3. The Kernel.struct/2 function, used to build structs
> > >> dynamically, won't check for required keys. Kernel.struct!/2
> > >> should be used if you want to check for required keys (and also
> > >> check that no extra keys are given)
> > >>
> > >> 4. defexception will leverage the same functionality
> > >>
> > >> *Implementation*
> > >>
> > >> Implementation-wise, structs will now defined a __struct__/1
> > >> function, besides the regular __struct__/0 function. It has not
> > >> been decided yet how such function will behave given it must work
> > >> both for compile-time (%User{}) and runtime (struct! User, %{})
> > >> checks.
> > >>
> > >> *Feedback*
> > >>
> > >> Now it is your turn. :)
> > >>
> > >> *José Valim*
> > >> www.plataformatec.com.br
> > >> Skype: jv.ptec
> > >> Founder and Director of R&D
> > >>
> > >
> > > --
> > > You received this message because you are subscribed to the Google
> > > Groups "elixir-lang-core" group.
> > > To unsubscribe from this group and stop receiving emails from it,
> > > send an email to [email protected].
> > > To view this discussion on the web visit
> > >
> https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4%2B5b%2BxxcvMOL-n6XyJ4mcQcumTU5B0AhjaTuc7qk-0P1g%40mail.gmail.com
> > > <
> https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4%2B5b%2BxxcvMOL-n6XyJ4mcQcumTU5B0AhjaTuc7qk-0P1g%40mail.gmail.com?utm_medium=email&utm_source=footer
> >
> > > .
> > > For more options, visit https://groups.google.com/d/optout.
> > >
> >
>
> --
> You received this message because you are subscribed to the Google Groups
> "elixir-lang-core" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/elixir-lang-core/20160525080713.279fe1dd.eksperimental%40autistici.org
> .
>
> For more options, visit https://groups.google.com/d/optout.
>
>
>
> --
> You received this message because you are subscribed to the Google Groups
> "elixir-lang-core" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4K5-pCjrDudw1MgXbGcwfhfn%3Da%2BpukmO00cgz1nsYg9Zg%40mail.gmail.com
> <https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4K5-pCjrDudw1MgXbGcwfhfn%3Da%2BpukmO00cgz1nsYg9Zg%40mail.gmail.com?utm_medium=email&utm_source=footer>
> .
> For more options, visit https://groups.google.com/d/optout.
>
>
>
>
> --
> You received this message because you are subscribed to the Google Groups
> "elixir-lang-core" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/elixir-lang-core/6C3AEDA3-34F1-4CED-8B4E-B1769C83D812%40silljays.com
> <https://groups.google.com/d/msgid/elixir-lang-core/6C3AEDA3-34F1-4CED-8B4E-B1769C83D812%40silljays.com?utm_medium=email&utm_source=footer>
> .
> For more options, visit https://groups.google.com/d/optout.
>
>
>
> --
> You received this message because you are subscribed to the Google Groups
> "elixir-lang-core" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/elixir-lang-core/1464186821.454905.618394761.3E78A7BC%40webmail.messagingengine.com
> <https://groups.google.com/d/msgid/elixir-lang-core/1464186821.454905.618394761.3E78A7BC%40webmail.messagingengine.com?utm_medium=email&utm_source=footer>
> .
>
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4Ji7JxRFN7fw72VNwqD%2BaqPZ3MQy7EJi-DcUztG-S1KKA%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to