It is sometimes if not often desirable to build up some Map or Keyword list 
and add or update values in such a way that takes into account the current 
state of the data, yet some of the current functions do not allow this to 
be done from a pipe.

A trivial example for instance:

```

map = %{filename: “thing.txt”}

map = Map.put_new(map, :base_path, "/")

map = Map.put_new(map, :file_path, Path.join([map.base_path, map.filename]))

```

This is begging to be piped, but Map.put_new_lazy/3’s function argument 
does not receive the current map.

For reference Map.put_new_lazy/3

https://github.com/elixir-lang/elixir/blob/a64d42f5d3cb6c32752af9d3312897e8cd5bb7ec/lib/elixir/lib/map.ex#L381

It is true we could simply use Kernel.then/2, but I think we can do better 
and make code easier to scan.

An example using pipes and Kernel.then/2

```

%{filename: “thing.txt”}

|> Map.put_new(:base_path, "/")

|> then(&(Map.put_new(&1, :file_path, Path.join([&1.base_path, 
&1.filename]))))

```

Kernel.then/2 is breaking up what could be a quick scan of the code.

We can smooth this out.

Here is an implementation on Map.put_new_lazy/3

```

​​  @spec put_new_lazy(map, key, ((map) -> value)) :: map

  def put_new_lazy(map, key, fun) when is_function(fun, 1) do

    case map do

      %{^key => _value} ->

        map

      %{} ->

        put(map, key, fun.(map))

      other ->

        :erlang.error({:badmap, other})

    end

  end

```

Then we could rewrite the original example like:

```

%{filename: “thing.txt”}

|> Map.put_new(:base_path, "/")

|> Map.put_new_lazy(:file_path, &(Path.join([&1.base_path, &1.filename]))))

```

If we wanted to go even further, we could even accept an arity 2 function 
and pass in both the map and the key.

Thoughts?


-- 
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/bc728f96-ff11-40c1-b90f-b412e241fbd9n%40googlegroups.com.

Reply via email to