> 1. Maps are slower (significantly enough to avoid IMHO), but do give the flexibility desired (1.79x slower, which could compound if in the wrong place)
Do you have a source for the 1.79 slower? I don't expect maps to be slower but, more importantly, the difference here should be negligible because options rarely exceed more than a dozen keys and in those scenarios lookups are in the order of single-digit microseconds (source <https://github.com/erlang/otp/issues/6139#issuecomment-1182995087>) *in the worst case*. So it seems counter productive to say you wouldn't pick the more flexible option because an operation will take 1.75us instead of 1us (assuming it is indeed slower). :) Plus maps have other benefits such as reading multiple keys at once which will certainly offset keyword lists. > Keyword lists must be matched in exact order, and flexibility with them is limited Yes, this is a pain point I see people running into. Especially given that you are not supposed to match on keyword lists. On Thu, Oct 27, 2022 at 11:01 PM Brandon Gillespie <bran...@cold.org> wrote: > The challenge I've seen, faced, and had team members face time and time > again, is that pattern matching only goes so far. The limitations are: > > 1. Maps are slower (significantly enough to avoid IMHO), but do give the > flexibility desired (1.79x slower, which could compound if in the wrong > place) > 2. Keyword lists must be matched in exact order, and flexibility with them > is limited > > It's the frequent edge cases that end up causing problems: they end up > being a little clunky in practical use. > > -Brandon > > > On 10/27/22 2:30 PM, José Valim wrote: > > [...] > > And Elixir has opted into pattern matching for this particular feature set. > > On Thu, Oct 27, 2022 at 10:19 PM Felipe Stival <v0id...@gmail.com> wrote: > >> 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 >> <https://groups.google.com/d/msgid/elixir-lang-core/CAKC64%2Bz6yHpK%3DJpN1fd7fgz9Z-m2UmsA0a852obGrjCpXzN1-w%40mail.gmail.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/CAGnRm4%2BsNgEUVdYQv_N6cu90O%2BzheNs1UPo5bZPw8-tT4UROhA%40mail.gmail.com > <https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4%2BsNgEUVdYQv_N6cu90O%2BzheNs1UPo5bZPw8-tT4UROhA%40mail.gmail.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/e77b7315-625a-4c8e-0e63-bbd03116fbbe%40cold.org > <https://groups.google.com/d/msgid/elixir-lang-core/e77b7315-625a-4c8e-0e63-bbd03116fbbe%40cold.org?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/CAGnRm4L%2BJ1zYcizc44RtK-tnX3QGSPojVhHTAXE3toWNyXbCew%40mail.gmail.com.