The arity issue can be dealt internally. def new(map, transform) when is_map(map) and is_function(transform, 1) do :maps.map( fn key, val -> {_new_key, new_value} = transform.({key, val}) new_value end, :maps.iterator(map) ) end On Wed, 13 Jan 2021 23:55:17 -0500 Austin Ziegler <halosta...@gmail.com> wrote:
> Building `Map.new/2` on `maps:map/2` would be incompatible, because > the transformation function differs in arity (`/1` for `Map.new/2` > and `/2` for `maps:map/2`). > > It would be possible to build `Map.new/2` such that it can tell the > difference between a `/1` or a `/2` when the first function is itself > a map or struct…but I’m not sure that would be an improvement, and it > would lead to potentially confusing documentation on when a `/2` > could be passed to `Map.new/2` and when a `/1` could be passed to > `Map.new/2`. > > If something is to be done, I believe that the original proposal, > surfacing `maps:map/2` as `Map.map/2` with the arguments flipped for > pipeline use _might_ be the best choice. At the same time, I’m not > _entirely_ sure that would be useful, as most pipelines transform > maps into lists and `maps:map/2` borks on a list: > > ```elixir > iex(1)> :maps.map(fn k, v -> v * 2 end, [{:a, 1}, {:b, 2}]) > warning: variable "k" is unused (if the variable is not meant to be > used, prefix it with an underscore) > iex:1 > > ** (BadMapError) expected a map, got: [a: 1, b: 2] > (stdlib 3.12.1) maps.erl:247: :maps.map(#Function<13.126501267/2 > in :erl_eval.expr/5>, [a: 1, b: 2]) > ``` > > At this point, even though I am happy to have discovered `maps:map/2` > from this discussion, that this would _not_ improve the usability of > Elixir on map transformation. > > A different question: how can we make these rich Erlang functions > much more visible to Elixir users like myself? I don’t care that the > arguments are “backwards” from the pipeline, because `maps:map/2` is > _incredibly_ useful and will improve some code that I have in > production. > > -a > > On Wed, Jan 13, 2021 at 7:54 PM eksperimental > <eksperimen...@autistici.org> wrote: > > > Great finding. > > Regardless the benchmarks, Map.new/2 should be optimized for maps > > using :maps.map/2, because as of now we are doing: map |> > > Enum.to_list() |> reduce list |> :lists.reverse() |> > > :maps.from_list() > > > > On Tue, 12 Jan 2021 14:09:26 -0800 (PST) > > "jonar...@gmail.com" <jonarnet...@gmail.com> wrote: > > > > > This usage of Map.new/2 is news to me (pun somewhat intended) and > > > pretty neat! However, I think that the naming alone may make it > > > less discoverable and a bit harder to grok when first > > > encountered. There also *might* be some performance gains from > > > using Erlang's maps:map for this task instead of maps:from_list > > > but I'm not sure. I'll do some profiling and find out. > > > > > > On Tuesday, January 12, 2021 at 5:01:51 PM UTC-5 > > > halos...@gmail.com wrote: > > > > > > > It’s not implemented with maps:map/2, but Map.new/2 should do > > > > the trick. > > > > > > > > `Map.new(map, fn {k, v} -> {k, v * 2} end)` > > > > > > > > That said, `maps:map/2` is available: > > > > > > > > `:maps.map(fn _k, v -> v * 2 end, %{x: 1, y: 2, z: 3})` > > > > > > > > It might be worth exploring whether `Map.map` would be > > > > useful/efficient enough to add for piping purposes. > > > > > > > > -a > > > > > > > > On Tue, Jan 12, 2021 at 4:51 PM jonar...@gmail.com > > > > <jonar...@gmail.com> wrote: > > > > > > > >> A common task is to iterate over a map performing some > > > >> operation thereby producing a new map. There are some ways to > > > >> do this in Elixir presently, the simplest probably being > > > >> for...into: > > > >> > > > >> for {key, val} <- map, into: %{} do > > > >> {key, val * 2} > > > >> end > > > >> > > > >> Enum.reduce/3 is also an option. However, Erlang provides a > > > >> simple function to replace the values of a map with maps:map > > > >> function: > > > >> > > > >> maps:map(fun(Key, Val) -> 2 * Val end, Map) > > > >> > > > >> I think an equivalent of this in Elixir would be very useful > > > >> either as Map.map/2 or Map.transform_values/2 like so: > > > >> > > > >> Map.transform_values(map, fn {_key, val} -> val * 2 end) > > > >> > > > >> I'm interested to hear if the community considers this a > > > >> worthwhile addition! > > > >> > > > >> -- > > > >> > > > > 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/d843c44b-e658-4d71-bb66-00c1e0a21ef7n%40googlegroups.com > > > >> < > > https://groups.google.com/d/msgid/elixir-lang-core/d843c44b-e658-4d71-bb66-00c1e0a21ef7n%40googlegroups.com?utm_medium=email&utm_source=footer > > > > > > >> . > > > >> > > > > > > > > > > > > -- > > > > Austin Ziegler • halos...@gmail.com • aus...@halostatue.ca > > > > http://www.halostatue.ca/ • http://twitter.com/halostatue > > > > > > > > > > > -- > > 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/5fff9633.1c69fb81.eec7e.37f2SMTPIN_ADDED_MISSING%40gmr-mx.google.com > > . > > > > -- 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/6000506f.1c69fb81.6dc1c.59d9SMTPIN_ADDED_MISSING%40gmr-mx.google.com.