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.

Reply via email to