Structs are implemented as maps. However, throughout more recent Elixir versions, some sugar has been added on top, which makes it easier to use a struct and more difficult to make certain mistakes. For instance: - Specifying default field values as part of `defstruct` - Compiler warnings when required struct fields are missing - Compiler warnings when duplicate struct fields are used - The possibility to override what exactly happens when someone writes `%Struct{}` or `%Struct{a: 1, b: 2}`.
This last point makes it very easy to add extra checks (or other logic) to the creation of a struct: By overridding the generated `__struct__/1`-method, we have control over how a struct is created, and can for instance provide more descriptive errors when someone is breaking the invariants of our struct. For who isn't aware of how this works: - `%Struct{}` desugars to Struct.__struct__() (which internally, unless itself overridden, calls `Struct.__struct__([])`) - `%Struct{some: 1, field: 2}` likewise desugars to `Struct.__struct__([some: 1, fields: 2])`. However, there is one case which currently cannot be extended, because it compiles down to a straight Erlang map update without using an intermediate overridable Elixir method: The syntax `%Struct{my_struct | some: a}`. Currently this directly is compiled to (the Erlang equivalent of): ``` case my_struct do x = %{__struct__: Struct} -> %{x | some: a} other -> raise BadStructError, struct: Struct, term: other end ``` --- I propose to add a new function, for instance called `__struct__(current_struct, changed_fields)`. Its implementation is exactly the code Elixir currently already uses for the struct update syntax (e.g. the one shown above). Elixir could call this method during compilation just like what is already done for __struct__/0 and __struct__/1 today. (or alternatively: just adding `@compile inline: [__struct__: 2]` might accomplish the same without having to evaluate it at compile-time?) Thus, the normal effect will be exactly what happens today, without any performance regressions or other problems. However, we now have the possibility of adding extra checks which will be executed whenever our struct is being updated. --- Thank you for your consideration, ~Marten / Qqwy -- 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 elixir-lang-core+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/3f2eb5f4-6f34-462d-8463-10fe2207524bn%40googlegroups.com.