Good idea! I searched through github to find more usecases like that to
corroborate this change, and here's what I found:

- 972 results for just `|> maybe_put`:
https://github.com/search?q=language%3AElixir+%22%7C%3E+maybe_put%22&type=code
- 214 results for `then(&if...`, where the majority's `else` clause was
just `&1`:
https://github.com/search?q=language%3AElixir+%22%7C%3E+then%28%22+%26if&type=code

This *feels* statistically relevant, considering the occurrence of `|> then`
<https://github.com/search?q=language%3AElixir+%22%7C%3E+then%22&type=code>
is ~6.2k.

I also noticed that most of the uses didn't need the predicate to be a
function (and I think in this cases maybe using `|> case do` is even
better, and the missing `else` clause won't be a problem here), so maybe
this could be even simpler by just taking a value as the condition instead.

Also I'm ok with the `then_if` implementation, but I personally still
prefer the `then(..., if: pred)` as it reads better to me, but I understand
it might be too different from the rest of the kernel code.

Em dom., 4 de ago. de 2024 às 00:15, Jean Klingler <sabiw...@gmail.com>
escreveu:

> Coming back to some of my projects, I indeed found a bunch of similar
> cases, e.g. maybe_put_assoc, so even if I'm still on the fence I do see
> your point.
>
> Assuming we introduce it, I'd find it more natural API-wise to have the
> condition first and then the action, which might be why the nested `if`
> felt more natural to me (consistent with `if`, other conditionals, and also
> Clojure's cond).
>
>   |> then_if(fn_ -> modified_since end, &Req.put_header(&1,
> "If-Modified-Since", modified_since))
>
>
> Le dim. 4 août 2024 à 11:22, Caio Oliveira <caio...@gmail.com> a écrit :
>
>> Yup, that’s what I usually do, but I see this in many places.
>> `maybe_put_header`, `maybe_prepend`, etc., which makes me think that an
>> abstraction would be convenient. And yeah, I wrote a `maybe_then`
>> initially, but thought it was simple and convenient enough to be in the
>> kernel.
>>
>> On Sat, 3 Aug 2024 at 22:42 Jean Klingler <sabiw...@gmail.com> wrote:
>>
>>> Thank you for providing a concrete example.
>>>
>>> Also subjective but I find the following more readable
>>>
>>>   |> then(&if(modified_since, do: Req.put_header(&1,
>>> "If-Modified-Since", modified_since), else: &1))
>>>
>>> than
>>>
>>>   |> then(&Req.put_header(&1, "If-Modified-Since", modified_since), if:
>>> fn_ -> modified_since end)
>>>
>>> But perhaps this case might benefit from introducing a private function
>>> rather than relying on `then`, especially if this is a recurrent use-case
>>> in your module/project:
>>>
>>> defp maybe_add_header(req, _key, nil), do: req
>>> defp maybe_add_header(req, key, value), do: Req.put_header(req, key,
>>> value)
>>>
>>> ...
>>> |> maybe_add_header("If-Modified-Since", modified_since)
>>> |> maybe_add_header("X-Entity-Id", entity_id)
>>>
>>> It should also be easy define your own then_if/3 macro if you really
>>> prefer the clojure style.
>>>
>>>
>>> Le dim. 4 août 2024 à 09:59, Caio Oliveira <caio...@gmail.com> a écrit :
>>>
>>>> True, although personally I find the one-line `if` kind of confusing,
>>>> especially when I was newer to the language.
>>>>
>>>> > Additionally, your suggestion only implies what happens if `pred` is
>>>> falsy while mine is clear.
>>>>
>>>> This almost convinced me, to be honest! But on the flip side this makes
>>>> it possible for you to forget to add a `else` clause, and just end up with
>>>> a `nil` that is potentially hard to find where it came from.
>>>>
>>>> Jose replied this in the PR (including here to centralize the
>>>> discussion and not spam the PR and his email there):
>>>>
>>>> > I personally would prefer to write the original code or use no
>>>> pipeline at all. I don’t think the gain in conciseness justifies the loss
>>>> in readability.
>>>>
>>>> I'd say I agree with it 99% of the time, but there's this 1% that makes
>>>> me miss Clojure's `cond->`
>>>> <https://clojuredocs.org/clojure.core/cond-%3E>. The concrete example
>>>> that made me write this PR was this: I'm writing a small internal library
>>>> to build requests for a third party service. There are some options that,
>>>> if included, requires me to add headers to a request. The code looks
>>>> something like this:
>>>>
>>>> ```elixir
>>>> def request_entity(opts) do
>>>>   modified_since = Keyword.get(opts, :modified_since)
>>>>   entity_id = Keyword.get(opts, :entity_id)
>>>>
>>>>   Req.new(url: "example.com")
>>>>   |> add_x()
>>>>   |> authorize()
>>>>   |> add_body()
>>>>   |> then(&if(modified_since, do: Req.put_header(&1,
>>>> "If-Modified-Since", modified_since), else: &1))
>>>>   |> then(&if(entity_id, do: Req.put_header(&1, "X-Entity-Id",
>>>> entity_id), else: &1))
>>>>   |> Req.request()
>>>> end
>>>> ```
>>>>
>>>> And I'd much rather write something like this instead:
>>>>
>>>> ```elixir
>>>> def request_entity(opts) do
>>>>   modified_since = Keyword.get(opts, :modified_since)
>>>>   entity_id = Keyword.get(opts, :entity_id)
>>>>
>>>>   Req.new(url: "example.com")
>>>>   |> add_x()
>>>>   |> authorize()
>>>>   |> add_body()
>>>>   |> then(&Req.put_header(&1, "If-Modified-Since", modified_since), if:
>>>> fn_ -> modified_since end)
>>>>   |> then(&Req.put_header(&1, "X-Entity-Id", entity_id), if: fn _ ->
>>>> entity_id end)
>>>>   |> Req.request()
>>>> end
>>>> ```
>>>>
>>>> You can see conciseness is not the point*, but readability, robustness
>>>> and convenience (a very subjective feeling, so feel free to ignore the last
>>>> one).
>>>>
>>>> Lastly, I know I could change the code in a million ways to avoid the
>>>> pattern altogether, maybe even resulting in a cleaner result, but I feel
>>>> this small addition would be a nice to have, and is something I miss, even
>>>> if rarely.
>>>>
>>>> * I left the conciseness out of the picture because I think it's way
>>>> less important, but it does play a bit of a part. The actual example ends
>>>> up needing to break the `if` into more lines, which doesn't read as good in
>>>> the middle of the piping.
>>>> Em sábado, 3 de agosto de 2024 às 19:09:10 UTC-3, gva...@gmail.com
>>>> escreveu:
>>>>
>>>>> You can already capture the `if` and do it as a one-liner
>>>>>
>>>>> x |> then(&if(pred(&1), do: f(&1), else: &1))
>>>>>
>>>>> so you don't gain much yet add more complexity. Additionally, your
>>>>> suggestion only implies what happens if `pred` is falsy while mine is
>>>>> clear.
>>>>>
>>>>> -Greg Vaughn
>>>>>
>>>>> > On Aug 3, 2024, at 4:16 PM, Caio Oliveira <cai...@gmail.com> wrote:
>>>>> >
>>>>> > x
>>>>> > |> then(fn val ->
>>>>> > if pred(&1) do
>>>>> > f(val)
>>>>> > else
>>>>> > val
>>>>> > end)
>>>>> >
>>>>> > Into this:
>>>>> >
>>>>> > x |> then(&f/1, if: &pred/1)
>>>>>
>>>>>
>>>>> --
>>>>
>>> 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/3c468ed7-1db6-46e3-bf23-45c21e501b3bn%40googlegroups.com
>>>> <https://groups.google.com/d/msgid/elixir-lang-core/3c468ed7-1db6-46e3-bf23-45c21e501b3bn%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>> .
>>>>
>>> --
>>> You received this message because you are subscribed to a topic in the
>>> Google Groups "elixir-lang-core" group.
>>> To unsubscribe from this topic, visit
>>> https://groups.google.com/d/topic/elixir-lang-core/uM_M-DWh42A/unsubscribe
>>> .
>>> To unsubscribe from this group and all its topics, 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/CANnyohay83mzBJRgz%3Dy8RZ6cp257u4t8zSfyMKMOfqmSTMvY2A%40mail.gmail.com
>>> <https://groups.google.com/d/msgid/elixir-lang-core/CANnyohay83mzBJRgz%3Dy8RZ6cp257u4t8zSfyMKMOfqmSTMvY2A%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/CAJLj4H9%3DsUxyupijoKeJbY1TVYQbjoGF7ALzG9_UT8LF8d655A%40mail.gmail.com
>> <https://groups.google.com/d/msgid/elixir-lang-core/CAJLj4H9%3DsUxyupijoKeJbY1TVYQbjoGF7ALzG9_UT8LF8d655A%40mail.gmail.com?utm_medium=email&utm_source=footer>
>> .
>>
> --
> You received this message because you are subscribed to a topic in the
> Google Groups "elixir-lang-core" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/elixir-lang-core/uM_M-DWh42A/unsubscribe
> .
> To unsubscribe from this group and all its topics, 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/CANnyohZzP5KK-JoXV4BdSg4oGjzgW4AfxOeDu6V7SDqBopR0Ww%40mail.gmail.com
> <https://groups.google.com/d/msgid/elixir-lang-core/CANnyohZzP5KK-JoXV4BdSg4oGjzgW4AfxOeDu6V7SDqBopR0Ww%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/CAJLj4H8tdQsK_bpxJXaYQawdLLOsYFt%2BKLL28yDqqbv1rUNP5A%40mail.gmail.com.

Reply via email to