I actually like passing options more. In fact, I wonder why is derive an
attribute, and not an option?
Something like,
defstruct [:name, :age], derive: Poison.Encoder, enforce: [:name]
seems more idiomatic to me.
On Wednesday, May 25, 2016 at 5:11:48 PM UTC+2, José Valim wrote:
>
> 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]
> <javascript:>> 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]
>> <javascript:>> 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]
>> <javascript:>> 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] <javascript:>> 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] <javascript:>> 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] <javascript:>> 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] <javascript:>.
>> > > 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] <javascript:>.
>> 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] <javascript:>.
>> 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] <javascript:>.
>> 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] <javascript:>.
>> 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/532823d4-cb24-4ca9-8c3a-d8109c163c62%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.