Thinking about it, can you solve the original problem with reduce?
```elixir
new_values = %{
foo: 10,
bar: 20
}
Enum.reduce(map, %{}, fn
{key, nil}, acc -> Map.put(acc, key, Map.get(new_values, key))
{key, value}, acc -> Map.put(acc, key, value)
end)
```
Best
Adam
> On 5 Jun 2020, at 15:10, Leandro Cesquini Pereira
> <[email protected]> wrote:
>
> `maybe` is a common prefix for functions that may or may not do something, eg:
>
> https://github.com/elixir-lang/elixir/blob/779ccdb7564d587dfdadc1285a4dc57eb24768a1/lib/logger/lib/logger.ex#L1074
>
> https://github.com/elixir-lang/elixir/blob/779ccdb7564d587dfdadc1285a4dc57eb24768a1/lib/elixir/lib/file.ex#L1796
>
> And so on...
>
> So I'd propose to call it `maybe_run`, just `maybe`, or something with
> `maybe`.
>
> On Friday, June 5, 2020 at 9:48:56 AM UTC-4, Adam Lancaster wrote:
> We have something similar in our code base we called the Maybe.Pipe: ~>
>
>
>> On 5 Jun 2020, at 14:41, Piotr Szmielew <[email protected] <javascript:>>
>> wrote:
>>
>> maybe it should be called run_if? so, something like this:
>>
>> defmacro run_if(piped_value, condition, fun) do
>> quote do
>> if unquote(condition) do
>> unquote(fun).(unquote(piped_value))
>> else
>> unquote(piped_value)
>> end
>> end
>> end
>>
>> and then used as:
>>
>> %{a: 1, b: 2}
>> |> X.run_if(1 == 2, &Map.put(&1, :foo, "foo"))
>> |> X.run_if(1 == 1, &Map.put(&1, :foo, "bar"))
>> # => %{a: 1, b: 2, foo: "bar"}
>>
>> On Fri, Jun 5, 2020 at 3:27 PM José Valim <[email protected] <javascript:>>
>> wrote:
>> Hi Riccardo,
>>
>> This is an interesting proposal! Unfortunately if the value you want to
>> compute is expensive, then you need to fallback to the usual `if` approach.
>> This is also specific to maps. It may be worth considering a more general
>> purpose mechanism, for example:
>>
>> map
>> |> update_if(foo != nil, &Map.put(&1, :foo, foo))
>> |> update_if(bar != nil, &Map.put(&1, :bar, normalize_bar(bar)))
>>
>> Being in Kernel also allows us to write it as a macro, which can be further
>> optimized. Not sure if update_if is the best name though. Suggestions and
>> comparisons to other languages are welcome.
>>
>> On Fri, Jun 5, 2020 at 12:36 PM Riccardo Binetti <[email protected]
>> <javascript:>> wrote:
>> Hi everybody,
>>
>> this is my first proposal so I hope I get the format right, I've already
>> checked in the mailing list and I haven't found similar proposals.
>>
>> Problem
>>
>> When manually constructing a map using external options or the result of a
>> pattern match on a struct, I often find myself in the situation where I have
>> to add a value only if it is non-nil.
>>
>> The possible approaches available today are these
>>
>> Using if
>>
>>
>> def some_fun(s) do
>> MyStruct{
>> foo: foo,
>> bar: bar,
>> baz: baz
>> } = s
>>
>> map = %{a: "hello", b: 42}
>>
>> map =
>> if foo do
>> Map.put(map, :foo, foo)
>> else
>> map
>> end
>>
>> map =
>> if bar do
>> Map.put(map, :bar, bar)
>> else
>> map
>> end
>>
>> if bar do
>> Map.put(map, :baz, baz)
>> else
>> map
>> end
>> end
>>
>>
>> This is the obvious solution, but it gets very verbose very quickly
>>
>>
>> Populating the map and then filtering
>>
>> def some_fun(s) do
>> MyStruct{
>> foo: foo,
>> bar: bar,
>> baz: baz
>> } = s
>>
>> %{a: "hello", b: 42}
>> |> Map.put(:foo, foo)
>> |> Map.put(:bar, bar)
>> |> Map.put(:baz, baz)
>> |> Enum.filter(fn {_k, v} -> v end)
>> |> Enum.into(%{})
>> end
>>
>> This is more concise, but it creates intermediate maps that are immediately
>> thrown away. Moreover, if the initial map is very large, the filter
>> operation is expensive since it traverses the whole map.
>>
>>
>> Implementing a maybe_put helper function
>>
>> def some_fun(s) do
>> MyStruct{
>> foo: foo,
>> bar: bar,
>> baz: baz
>> } = s
>>
>> %{a: "hello", b: 42}
>> |> maybe_put(:foo, foo)
>> |> maybe_put(:bar, bar)
>> |> maybe_put(:baz, baz)
>> end
>>
>> defp maybe_put(map, _key, nil), do: map
>> defp maybe_put(map, key, value), do: Map.put(map, key, value)
>>
>> This is the solution I end implementing almost always. It is present in
>> multiple modules across the codebase I work on (and/or put in a generic
>> Utils module), and talking with my colleagues I found out that is a utility
>> function that they also have to implement often and it has turned up at
>> least a couple times[1][2] also in the Elixir Forum.
>>
>> [1]
>> https://elixirforum.com/t/elixir-way-to-conditionally-update-a-map/17952/21?u=rbino
>>
>> <https://elixirforum.com/t/elixir-way-to-conditionally-update-a-map/17952/21?u=rbino>
>> [2]
>> https://elixirforum.com/t/is-there-way-to-create-map-and-conditionally-exclude-some-keys/23315/5?u=rbino
>>
>> <https://elixirforum.com/t/is-there-way-to-create-map-and-conditionally-exclude-some-keys/23315/5?u=rbino>
>>
>> This brings me to my proposal, which is a more generic version of maybe_put.
>>
>> Proposal
>>
>> Add Map.put_if/4 to the Map module. This is more generic (and imho clearer)
>> than maybe_put and can be used to solve the same problem without creating
>> intermediate results and allowing the code to be clear and concise.
>>
>>
>> def some_fun(s) do
>> MyStruct{
>> foo: foo,
>> bar: bar,
>> baz: baz
>> } = s
>>
>> %{a: "hello", b: 42}
>> |> Map.put_if(:foo, foo, foo != nil)
>> |> Map.put_if(:bar, bar, bar != nil)
>> |> Map.put_if(:baz, baz, baz != nil)
>> end
>>
>> Let me know if you need any other information.
>> --
>> Riccardo
>>
>> --
>> 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 [email protected] <javascript:>.
>> To view this discussion on the web visit
>> https://groups.google.com/d/msgid/elixir-lang-core/f513b901-fd93-4f28-88a2-f496a3c84a21o%40googlegroups.com
>>
>> <https://groups.google.com/d/msgid/elixir-lang-core/f513b901-fd93-4f28-88a2-f496a3c84a21o%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 [email protected] <javascript:>.
>> To view this discussion on the web visit
>> https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4K_QVpD-eRG6JUOMYV5pVTLchpTgbO0fqN6pPCmuSL4NA%40mail.gmail.com
>>
>> <https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4K_QVpD-eRG6JUOMYV5pVTLchpTgbO0fqN6pPCmuSL4NA%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 [email protected] <javascript:>.
>> To view this discussion on the web visit
>> https://groups.google.com/d/msgid/elixir-lang-core/CANmTJ6thcegKJjb7aKPhtQoqfo5%3DCgJo2-KnORRg8B2UcEB%3D-A%40mail.gmail.com
>>
>> <https://groups.google.com/d/msgid/elixir-lang-core/CANmTJ6thcegKJjb7aKPhtQoqfo5%3DCgJo2-KnORRg8B2UcEB%3D-A%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 [email protected]
> <mailto:[email protected]>.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/elixir-lang-core/45a9ec20-f997-4fdf-a4c0-ea88388a8fabo%40googlegroups.com
>
> <https://groups.google.com/d/msgid/elixir-lang-core/45a9ec20-f997-4fdf-a4c0-ea88388a8fabo%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 [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/elixir-lang-core/4F9BCFD1-91CB-4A45-B6C2-BC1E534889DF%40channelviewestates.co.uk.