> 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 <bran...@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-core+unsubscr...@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-core+unsubscr...@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/CAGnRm4JvQTNeQQj0V5wA9R-qQuEW4pGEoyKi1tkYqqu5L8vQMQ%40mail.gmail.com.

Reply via email to