This library implements this functionality, albeit on a peculiar way: https://hex.pm/packages/defnamed. It suffers from the issues explained by Marc-André.
On Thu, Oct 27, 2022, 21:05 Marc-André Lafortune <marc-an...@marc-andre.ca> wrote: > If I understand your proposal, calling `do_a_thing(old: "older value", > new: "newer value")` would need to know the signature of `do_a_thing` at > *compile-time*. Among other things, two modules wouldn't be able to call > each other's functions this way, as one couldn't be compiled without the > other... Also there would be no way to know if `do_a_thing` uses named > function arguments, so any function call using keywords would introduce a > compile-time dependency. > > That being said, I miss Ruby's named arguments, and wish the default > syntax for Elixir was building maps instead of keywords, but that can't > change. Having a nice syntax for map arguments with defaults could be > interesting though. > On Thursday, 27 October 2022 at 09:59:48 UTC-4 Brandon Gillespie wrote: > >> Ordering of arguments is an age-old programming challenge (creating many >> bugs). Type checking and pattern matching help, but are also limited. We >> currently have two indirect ways of having named arguments, but both have >> challenges: >> >> 1. Keyword lists — pattern matching must match the exact order of the >> listed arguments, which doesn't help the issue here which is ordering, let >> alone optional arguments, leading to extraneous in-function calls to >> Keyword.get. >> 2. Maps — while this supports optional arguments, it has the overhead >> of creating and destructing a map for a simple function call. Benchmarking >> this vs ordered arguments shows it's 1.79x slower than simply using >> ordered >> arguments. That's an overhead that builds up on every function (I didn't >> benchmark keyword lists, sorry). >> 3. Existing syntax to handle named arguments as keywords should still >> be handled, for backwards compatibility, making it harder to do this sort >> of thing. >> >> To preface the proposal, I realize this may simply not be possible with >> the limitations of the parser/compiler that we have today. >> >> Proposal: >> >> Add a compile-time named/pinned argument syntax in the function >> declaration head, which allows the naming of arguments as if it were a >> keyword list, but instead, the keys are mapped to the variable names/pins >> and, if necessary, are rearranged to keep the ordering correct. >> >> This will not work with conventional keyword arguments, where one expects >> a keyword list—if using the named/pinned syntax, keyword arguments may not >> be used. It's one or the other, not both. >> >> If this named syntax exists on a function head, then a calling function >> may use the `name: value` syntax and it will align the values to the named >> argument at compile time (no keyword lists are used at runtime). >> >> Example: >> >> Using `&` as a reference for the naming (or possibly if not that, the >> asterisk): >> >> def do_a_thing(&new, &old) >> >> Would accept any of these calls, and in all cases the variable values >> within the called function would align properly: >> >> do_a_thing("newer value", "older value") >> do_a_thing(new: "newer value", old: "older value") >> do_a_thing(old: "older value", new: "newer value") >> >> Optional named arguments in the same manner as optional arguments today: >> >> def do_a_thing(&new, &old, &optional \\ "extra info") >> >> Optional ideas: >> >> >> 1. If rearranging the arguments at compile time is not easily >> feasible, it could simply just raise a compiler error when out of order, >> and then strip the names when they are properly ordered. >> 2. If using named/pinned arguments, always require them to be named >> (thus, the first example above would be invalid). However, this comes with >> its own challenge, notably what about when using pipelines? Perhaps just >> allow that. >> 3. If it's too challenging to use the same syntax as keyword lists, >> another naming convention could be used. It's just ... uglier. Perhaps if >> using `*` instead it would be on both sides (function head, and calling >> function), such as: >> >> def do_a_thing(*new, *old) >> ... >> do_a_thing(*new: "newer value", *old: "older value") >> > -- > 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/0928ddde-8ca2-4110-a223-d62b711529a7n%40googlegroups.com > <https://groups.google.com/d/msgid/elixir-lang-core/0928ddde-8ca2-4110-a223-d62b711529a7n%40googlegroups.com?utm_medium=email&utm_source=footer> > . > -- 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/CAKC64%2Bz6yHpK%3DJpN1fd7fgz9Z-m2UmsA0a852obGrjCpXzN1-w%40mail.gmail.com.