So the original proposal here is for introducing a named parameter syntax. The reason I like named parameters is b/c the order of parameters doesn't matter – when they do matter it's easy for refactoring to introduce hard to catch bugs. Pattern matching has been proposed as the idiomatic way to achieve argument order not mattering. If I understand correctly, the recommendation is to stuff arguments into a map just before a function call that itself immediately destructures them. While this approach does address my primary concern (ie parameter order), it has to be slower, right? I can imagine this having a non-trivial effect in a pipeline on a hot-path.
So the question for me, really, is how much quicker is passing ordered arguments vs creating then destructuring a map? If it's negligible then it's negligble, but if it's not then it would be nice to have an alternative. - Jake On Friday, October 28, 2022 at 9:47:31 AM UTC-4 José Valim wrote: > > Is this an expensive pattern because it generates a map only for the > next function to extract the keys and ignore the map? > > It depends on what you are comparing it with. Compared to simply passing > arguments, it is likely slower. Compared to keyword lists, likely faster. > > On Fri, Oct 28, 2022 at 3:41 PM Brandon Gillespie <bra...@cold.org> wrote: > >> Fair enough :) >> >> If I understand what you are saying: they are all maps because the source >> data comes from a map, and it's the method of extracting data from the map >> that differs (the algorithm), not the inherent nature of a map itself. >> >> I agree, and apologize for the mistaken assertion. >> >> However, what I didn't benchmark as i think about it, is what I often >> will see, which is the creation of a map simply to pass arguments — and >> this is more relevant to the request/need. The example was based on >> existing structs/maps and not creating them at each function call time. >> >> Instead, for example: >> >> def do_a_thing(%{key2: value2, key1: value1}) do ... >> >> I think it's becoming a common pattern to then construct the maps as part >> of the call, ala: >> >> do_a_thing(%{key1: 10, key2: 20}) >> >> Is this an expensive pattern because it generates a map only for the next >> function to extract the keys and ignore the map? >> >> -Brandon >> >> >> On 10/28/22 12:37 AM, José Valim wrote: >> >> >> >>> 1.79 times, as I read it, not 1.79us. And of course benchmarks being >>>> highly subjective, now that I retooled it it's at 2.12x slower (see notes >>>> at the very bottom for likely reasons why). >>>> >>> Correct. What I did is to take a reference value of 1us and multiplied >> it by 1.79, to say that at this scale those numbers likely won't matter. >> >>> The gist includes three scenarios: >>>> >>> Thanks for sharing. I won't go deep into this, as requested, but I want >> to point out that the conclusion "maps are slower (significantly enough to >> avoid)" is still incorrect for the benchmarks above. >> >> All of those benchmarks are using map patterns because both map.field and >> Map.get are also pattern matching on maps. >> >> map.field is equivalent to: >> >> case map do >> %{field: value} -> value >> %{} -> :erlang.error(:badkey) >> _ -> :erlang.error(:badmap) >> end >> >> Map.get/2 is equivalent to: >> >> case map do >> %{field: value} -> value >> %{} -> nil >> end >> >> To further drive this point home, you could rewrite the map_get one as: >> >> def map_get(engine) do >> map_get_take(engine.persist, engine, @take_keys, []) >> end >> >> defp map_get_take(engine, persist, [a | rest], out) do >> case {engine, persist} do >> {%{^a => value}, %{^a => value}} -> >> map_get_take(engine, persist, rest, [{a, value} | out]) >> >> _ -> >> map_get_take(engine, persist, rest, out) >> end >> end >> >> defp map_get_take(_, _, [], out), do: out >> >> And the numbers likely won't matter or be roughly the same. The point is: >> you are effectively benchmarking different algorithms and not the >> difference between map_get or map_pattern. >> >> I am only calling this out because I want to be sure no one will have >> "maps are slower (significantly enough to avoid)" as a take away from this >> discussion. >> >> > What if a syntax for matching on keyword lists that allowed for items >> in any position was added to Elixir? Something like (just shooting from the >> hip) `[…foo: bar]` ? Then you could have your cake and eat it too, right? >> >> Valid patterns and guards are dictated by the VM. We can't compile >> keyword lists lookups to any valid pattern matching and I would be >> skeptical about proposing such because we should avoid adding linear >> lookups to patterns. >> >> It is worth taking a step back. It is not only about asking "can we have >> this feature?". But also asking (at least) if the feature plays well with >> the other constructs in the language and if we can efficiently implement it >> (and I believe the answer is no to both). >> -- >> You received this message because you are subscribed to a topic in the >> Google Groups "elixir-lang-core" group. >> To unsubscribe from this topic, visit >> https://groups.google.com/d/topic/elixir-lang-core/Dbl6CL5TU5A/unsubscribe >> . >> To unsubscribe from this group and all its topics, send an email to >> elixir-lang-co...@googlegroups.com. >> To view this discussion on the web visit >> https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4L37yu8KVbhuM0gNkVYOzCeoXaKzTBk4aY4OLLRdgRRLg%40mail.gmail.com >> >> <https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4L37yu8KVbhuM0gNkVYOzCeoXaKzTBk4aY4OLLRdgRRLg%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-co...@googlegroups.com. >> To view this discussion on the web visit >> https://groups.google.com/d/msgid/elixir-lang-core/9f60ba0c-8403-e93f-d5fb-b3f55df88d14%40cold.org >> >> <https://groups.google.com/d/msgid/elixir-lang-core/9f60ba0c-8403-e93f-d5fb-b3f55df88d14%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/01432858-e854-4747-921a-230e6bbd7489n%40googlegroups.com.