[Proposal] Conditional pipe

138 views
Skip to first unread message

xward

unread,
Feb 2, 2022, 9:52:28 AM2/2/22
to elixir-lang-core
Hi !

A few months ago we added a conditional pipe in our code in our 120k+ line of elixir code and it turns out to be very useful.
The proposition is to contribute and add it to Elixir kernel, also to find out if we can do it better thanks to your feedback here.
  • Usecases
- avoid breaking a pipe chain to make an if test
```
def clean_list(list, real?) do
new_list =
list
|> do_something()

if real?, do: new_list |> do_stuff(), else: new_list
end
```

- avoid creating a bunch of pattern matching functions to do the same thing (even though this one is quite clean)
```
def clean_list(list, real?) do
list
|> do_something()
|> maybe_do_stuff(real?)
end

def maybe_do_stuff(list, true), do: list |> do_stuff()
def maybe_do_stuff(list, _), do: list
```

  • proposition usage example
```
def clean_list(list, real?) do
list
|> do_something()
# this can be named differently, or even create something funky like `|>?`
|> pipe_if(real?, do_stuff())
end
```

```
# Repo queries

MySchema
|> where(user_id: 12)
|> pipe_if(page_number > 0, offset(^(page_number * @page_size)))
|> Repo.all()

User
|> where([u], u.organisation_id == ^organisation_id)
|> pipe_if(only_admins?, where([u], u.admin == true))
|> Repo.all()
```

What do you think ?

Have a nice day !

Sven Gehring

unread,
Feb 2, 2022, 10:34:21 AM2/2/22
to elixir-l...@googlegroups.com
Hi,

Suppose the Repo query example is wrapped in a function that should return {:ok, [%User{}]} | {:error, :any},
how would one specify what is returned in the "else" case of a "pipe_if"? Is nothing returned?

I am not sure if I am missing something but all the use-cases I can think of can be solved with a "with" statement,
which adds the benefit of clean syntax, pattern matching and reacting differently to different "else" cases.

Best,
Sven 

--
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/97c0c216-99d1-4849-a56b-ca4ffab698f3n%40googlegroups.com.

Bruce Tate

unread,
Feb 2, 2022, 12:41:29 PM2/2/22
to elixir-l...@googlegroups.com
-1 from me. here's why:

A while ago, i built a library called ElixirPipes that allowed conditional pipes, and also different piping semantics. After the introduction of with, it basically went away. 

Generally, I use pipes when I am dealing with certainty, in the functional core. I use with when I am dealing with uncertainty. And I build a custom helper when I need to give something uncertain a more certain structure. So I see pipes and with as a continuum, and I use custom functions and even macros to work around them. 


---certain---
- pipes
- custom functions (maybe functions)
- custom types (e.g. introduce maybe type for special use cases)
- custom macros
- with
---uncertain---

Generally, in your use case, I would stay in pipes, but with a custom function: 

maybe_where(q, true|false, parms) as it would always return a valid type. 

If I needed lazy evaluation (your use case doesn't), I would move to a macro. 

Good idea, though. 

-bt



--

Regards,
Bruce Tate
CEO

Stefan Chrobot

unread,
Feb 2, 2022, 1:23:15 PM2/2/22
to elixir-l...@googlegroups.com
What do you think about using "then"?

def clean_list(list, real?) do
  list
  |> do_something()
  |> then(fn list -> if real?, do: do_stuff(list), else: list end)
  # or even shorter, though surprising
  # |> then(&if real?, do: do_stuff(&1), else: &1)
end

Not a huge fan of one-liner "if"s though. I think I'd like to see something more terse in Elixir - maybe a ternary ?: or an "if" variation that works only with expressions so we could drop do/else.

But coming back to your proposal: for me to get behind this, the construct would have to support pattern matching as I think that's the more common way of branching the code than boolean conditions.


Best,
Stefan



Reply all
Reply to author
Forward
0 new messages