Thank y'all for the replies.
@Ben :
in my particular instance, I don't already have a second map I want to merge, but rather I'm adding several {k,v} pair to the map. So, I'd agree that piping thru multiple Map.puts best represents what I'm really trying to do.
I am definitely curious about how things work under the hood. Do you have any additional insights into why it is that building a list of tuples and call :maps.from_list is faster than the Map.puts? Is it function call overhead of the Map.puts? or would it have to do with the :maps.from_list call (perhaps) only having to construct the tree one time since it has visibility to all the keys at once.. instead of repeatedly inserting, and potentially having to restructure the tree during building?
@James :
I guess to clarify, is I was thinking on the Map.put call, the incoming map would be passed by reference, but an entirely new copy of the map would be created that included the new {k,v} pair. But it seems, from reading more about the persistent data structures, that the common parts of the old/ new map would be shared .. preventing an entirely new copy being created.
For the HAMT, I suppose there could be places the new key would land that could cause the old and new trees to be quite a bit different, which would require more under the hood work.
I'm really glad that I asked this question, because I'm familiar with the nitty gritty's of various data structures as implemented in an imperative language, and naively didn't think much about how they'd be different in a functional language until recently. I've been writing in Erlang for about three years now and only recently began using Elixir, so functional languages/ programming still feels relatively new.
Thanks again for the insights!