I have answered why @override true does not work on the forum. The gist is that @impl true works for behaviors even if they don't provide overridable inplementations. @override true would only make sense for defoverridable and that would unnecessarily constrain us.
On Thu, Jan 19, 2017 at 13:12 Drew Olson <[email protected]> wrote: > These changes all seem great. I also prefer `@override true` to `@impl > true`. > > On Thu, Jan 19, 2017 at 1:09 PM, <[email protected]> wrote: > > I like all these changes - and I agree with Norbert, I like `@override > true` better than `@impl true` > > But I'm happy to have the functionality whatever the name. +1 > > On Thursday, January 19, 2017 at 4:35:05 AM UTC-8, Norbert Melzer wrote: > > This very same post is on elixirforum ( > https://elixirforum.com/t/behaviours-defoverridable-and-implementations/3338) > as well, and I commented there. I will post the same comment here and also > continue discussion here if it happens: > > > I really like the idea, but I think that @impl might get confused with > something related to protocols because of Kernel.defimpl/3, > Protocol.assert_impl!/2, and Protocol.extract_impls/2 beeing the only > things mentioning "impl" in elixir until now. Therefore I'd opt for > something like @override as in Java. > > José Valim <[email protected]> schrieb am Do., 19. Jan. 2017 > um 12:52 Uhr: > > Hi everyone, > > One of the features added to Elixir early on to help integration with > Erlang code was the idea of overridable function definitions. This is what > allowed our GenServer definition to be as simple as: > > defmodule MyServer do > > use GenServer > > end > > Implementation-wise, use GenServer defines functions such as: > > def terminate(reason, state) do > > :ok > > end > > and then mark them as overridable: > > defoverridable terminate: 2 > > As the community grew, defoverridable/1 started to show some flaws in its > implementation. Furthermore, the community did not always follow up on best > practices, often times marking functions as overridable but without > defining a proper Behaviour behind the scenes. > > The goal of this proposal is to clarify the existing functionality and > propose extensions that will push the community towards best practices. > Using @optional_callbacks > > In the example above, we have used defoverridable terminate: 2 to make > the definition of the terminate/2 function optional. > > However, in some cases, the use of defoverridable seems to be unnecessary. > For instance, we provide a default implementation for handle_call/3 and > mark it as overridable, but the default implementation simply raises when > invoked. That's counter-intuitive as it would be best to simply not define > a default implementation in the first place, truly making the > handle_call/3 callback optional. > > Luckily, Erlang 18 added support for marking callbacks as optional, which > we support on Elixir v1.4. We propose Elixir and libraries to leverage this > feature and no longer define default implementations for the handle_* > functions > and instead mark them as optional. > > Instead of the version we have today: > > defmodule GenServer do > > @callback handle_call(message, from, state) > > > > defmacro __using__(_) do > > quote do > > @behaviour GenServer > > > > def handle_call(_message, _from, _state) do > > raise "handle_call/3 not implemented" > > end > > > > # ... > > > > defoverridable handle_call: 3 > > end > > end > > end > > We propose: > > defmodule GenServer do > > @callback handle_call(message, from, state) > > @optional_callbacks handle_call: 3 > > > > defmacro __using__(_) do > > quote do > > @behaviour GenServer > > > > # ... > > end > > end > > end > > The proposed code is much simpler conceptually since we are using the > @optional_callbacks feature instead of defoverridable to correctly mark > optional callbacks as optional. defoverridable will still be used for > functions such as terminate/2, which are truly required. > > For developers using GenServer, no change will be necessary to their code > base. The goal is that, by removing unnecessary uses of defoverridable/1, > the Elixir code base can lead by example and hopefully push the community > to rely less on such tools when they are not necessary. > The @impl annotation > > Even with the improvements above, the usage of defoverridable/1 and > @optional_callbacks still have one major downside: the lack of warnings > for implementation mismatches. For example, imagine that instead of > defining handle_call/3, you accidentally define a non-callback > handle_call/2. Because handle_call/3 is optional, Elixir won't emit any > warnings, so it may take a while for developers to understand why their > handle_call/2 callback is not being invoked. > > We plan to solve this issue by introducing the @impl true annotation that > will check the following function is the implementation of a behaviour. > Therefore, if someone writes a code like this: > > @impl true > > def handle_call(message, state) do > > ... > > end > > The Elixir compiler will warn that the current module has no behaviour > that requires the handle_call/2 function to be implemented, forcing the > developer to correctly define a handle_call/3 function. This is a > fantastic tool that will not only help the compiler to emit warnings but > will also make the code more readable, as any developer that later uses the > codebase will understand the purpose of such function is to be a callback > implementation. > > The @impl annotation is optional. When @impl true is given, we will also > add @doc false unless documentation has been given. We will also support > a module name to be given. When a module name is given, Elixir will check > the following function is an implementation of a callback in the given > behaviour: > > @impl GenServer > > def handle_call(message, from, state) do > > ... > > end > > defoverridable with behaviours > > While @impl will give more confidence and assistance to developers, it is > only useful if developers are defining behaviours for their contracts. > Elixir has always advocated that a behaviour must always be defined when a > set of functions is marked as overridable but it has never provided any > convenience or mechanism to enforce such rules. > > Therefore we propose the addition of defoverridable BehaviourName, which > will make all of the callbacks in the given behaviour overridable. This > will help reduce the duplication between behaviour and defoverridable > definitions and push the community towards best practice. Therefore, > instead of: > > defmodule GenServer do > > defmacro __using__(_) do > > quote do > > @behaviour GenServer > > > > def init(...) do ... end > > def terminate(..., ...) do ... end > > def code_change(..., ..., ...) do ... end > > > > defoverridable init: 1, terminate: 2, code_change: 3 > > end > > end > > end > > We propose: > > defmodule GenServer do > > defmacro __using__(_) do > > quote do > > def init(...) do ... end > > def terminate(..., ...) do ... end > > def code_change(..., ..., ...) do ... end > > defoverridable GenServer > > end > > end > > end > > By promoting new defoverridable API above, we hope library developers will > consistently define behaviours for their overridable functions, also > enabling developers to use the @impl true annotation to guarantee the > proper callbacks are being implemented. > > PS: Notice defoverridable always comes after the function definitions, > currently and as well as in this proposal. This is required because Elixir > functions have multiple clauses and if the defoverridable came before, we > would be unable to know in some cases when the overridable function > definition ends and when the user overriding starts. By having > defoverridable at the end, this boundary is explicit. > Summing up > > This proposal promotes the use the of @optional_callbacks, which is > already supported by Elixir, and introduces defoverridable(behaviour_name) > which > will push library developers to define proper behaviours and callbacks for > overridable code. > > We also propose the addition of the @impl true or @impl > behaviour_nameannotation, > that will check the following function has been listed as a callback by any > behaviour used by the current module. > > Feedback? > > > *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/CAGnRm4J2EE%3DvM9k6hz-wsASfYUuTs%2B_JwRW4cnyFn-eYAcuD0g%40mail.gmail.com > <https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4J2EE%3DvM9k6hz-wsASfYUuTs%2B_JwRW4cnyFn-eYAcuD0g%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/0c46c5d9-3952-49a2-adfb-9eae6791eb86%40googlegroups.com > <https://groups.google.com/d/msgid/elixir-lang-core/0c46c5d9-3952-49a2-adfb-9eae6791eb86%40googlegroups.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/CAN3B1jd_d3ZshY8hpE0eFYx-j5Fd_2dac5_CoB-vrWMYWaVsow%40mail.gmail.com > <https://groups.google.com/d/msgid/elixir-lang-core/CAN3B1jd_d3ZshY8hpE0eFYx-j5Fd_2dac5_CoB-vrWMYWaVsow%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/CAGnRm4JrRqrM-ORqPLwaMQSsaXC91OyoLnz3o81cAheXqmtiCA%40mail.gmail.com. For more options, visit https://groups.google.com/d/optout.
