I agree this is a good proposal but Wojtek unfortunately touched on a point
that I don't know how to address.

There are currently 4 *_lazy functions and, if we add this functionality to
one of them, it would soon be expected that all of them support it. The
problem is that the functions that already receive an argument, such as
replace_lazy, cannot be easily modified to accommodate this feature.

Since replace_lazy already accepts the current value as argument, in order
to accept the map and potentially the key we would have the following
inconsistencies:

1. If a function of single arity is given, then it must receive the key
(which is inconsistent with the others which receive the map as first
argument)
2. If a function of arity 2 is given, then the map should either be:
  a. the first argument, which means the "key" argument is moving around,
which is confusing
  b. the second argument, which means it does not mirror the order of
arguments given to Map.replace_lazy itself, which is also confusing

Also note that historically we have not added features, such as new
functions, for pipe-ability reasons. In any case, I think this would have
been fine but given it will introduce inconsistencies into stdlib, then I
don't believe it is worth it.

On Sat, May 20, 2023 at 3:58 AM Kurtis Rainbolt-Greene
<kurtis@rainbolt-greene.online> wrote:

> I want to second this, the value of pipe-ready functions is an obvious one
> to me, it has so many downstream bonuses. If we improve this by one step or
> many I don't care, as I think naturally this will be kept in mind anyways
> for future functions.
>
> On Fri, May 19, 2023 at 6:46 AM Christian Trosclair <
> christian.troscl...@dockyard.com> wrote:
>
>>
>> For me, I run into this often enough, that I wish this was a thing.
>> Clearly, YMMV.
>>
>> Strictly speaking, yes. But I think just updating the *_lazy versions is
>> sufficient for the level of consistency already present. I mean, there's no
>> Map.put_lazy when there clearly could be and I don't think not changing
>> update makes things worse. (sorry for the double negatives there)
>> The documentation for a revised Map.update would need to be careful.
>> There' would be a lot going on to explain.
>> On Friday, May 19, 2023 at 7:54:46 AM UTC-4 woj...@wojtekmach.pl wrote:
>>
>>> I believe an apples-to-apples comparison would be:
>>>
>>>     # before
>>>     x
>>>     |> then(&Map.put_new_lazy(&1, :file_path, fn ->
>>> Path.join([&1.base_path, &1.filename]) end))
>>>
>>>     # after
>>>     x
>>>     |> Map.put_new_lazy(:file_path, &Path.join([&1.base_path,
>>> &1.filename]))
>>>
>>> And I think it does read better.
>>>
>>> That being said, personally I don’t think I have commonly needed
>>> something like this though and I’d just break out of a pipe and move on. :)
>>> If we add this precedent, that the function receives the input as one of
>>> the arguments, should we update other functions for consistency too? Do we
>>> have an Map.update accepting a 2-arity function? (Is the map the first or
>>> the second argument?!)
>>>
>>> On 19 May 2023, at 13:30, Christian Trosclair <christian...@dockyard.com>
>>> wrote:
>>>
>>> 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-co...@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
>>> <https://groups.google.com/d/msgid/elixir-lang-core/bc728f96-ff11-40c1-b90f-b412e241fbd9n%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 elixir-lang-core+unsubscr...@googlegroups.com.
>> To view this discussion on the web visit
>> https://groups.google.com/d/msgid/elixir-lang-core/2ea1ed78-45eb-4299-8bfe-2a5f96984709n%40googlegroups.com
>> <https://groups.google.com/d/msgid/elixir-lang-core/2ea1ed78-45eb-4299-8bfe-2a5f96984709n%40googlegroups.com?utm_medium=email&utm_source=footer>
>> .
>>
>
>
> --
> Kurtis Rainbolt-Greene,
> Software Developer & Founder of Difference Engineers
> 202-643-2263
>
> --
> 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/CAMhJPGg3LeNr8zi_5iS%3Dujex1KTSXufQAh8O29vY1Er5ZGaUPA%40mail.gmail.com
> <https://groups.google.com/d/msgid/elixir-lang-core/CAMhJPGg3LeNr8zi_5iS%3Dujex1KTSXufQAh8O29vY1Er5ZGaUPA%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/CAGnRm4JQ%2BWsd-PaJ1_X586SjhEzKqtan2YRXabMduBnPGfx0vQ%40mail.gmail.com.

Reply via email to