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.
