rvirding

rvirding

Creator of Erlang

This is a beauty. Seen in the wild, not from me or my colleagues.

interval
  |> Kernel.-(time_elapsed)
  |> max(0)
  |> schedule_events()

Showing Posts 1 to 10

alco

alco

It is much harder to grasp than

remaining_time = max(0, interval - elapsed_time)
schedule_events(remaining_time)
10
Post #1
peerreynders

peerreynders

Given many developers proclivity towards inline functions (of any size) I suspect that in a “pipeless” environment

schedule_events(max(interval - time_elapsed, 0))

would have been the likely result (which I find less clear (harder to parse) than the two line version).

jeremyjh

jeremyjh

I agree that Alco’s forumulation is best, but for short phrases its idiomatic to avoid unnecessary assignment, and pipes are the best way to do that in many cases.

More readable than the nested calls is:

max(0, interval - elapsed_time) |> schedule_events()

Which, seems fine to me, but Credo will give me **** about not starting a pipe with a value so I have to write

0 |> max(interval - elapsed_time) |> schedule_events()

I don’t think that’s much better than what we started with.

peerreynders

peerreynders

Unnecessary from what perspective?

remaining_time = max(0, interval - elapsed_time)

Sure the computer doesn’t need it but:

p. 15, Refactoring: Improving the design of existing code; 1999

The right hand side of the assignment focuses on what needs to be done - the left hand side enlightens us why it’s being done.

Sometimes I wonder whether these “idioms” date back to when this was normal

z = max(0, x - y)
schedule_events(z)

That z is unnecessary.

Pipes can be similarly affected by bad or lack of naming which is what is really going on in the OP.

interval
|> calc_remaining_time(time_elapsed)
|> make_positive_value()
|> schedule_events()

which should really become

interval
|> remaining_time(time_elapsed)
|> schedule_events()

but even that seems forced compared to

remaining_time = max(0, interval - elapsed_time)
schedule_events(remaining_time)
jeremyjh

jeremyjh

Unnecessary from the programmer’s perspective, of course. In some cases it’s necessary to make code understandable, but it isn’t always of course - that’s why the operator exists.

josevalim

josevalim

Creator of Elixir

I wouldn’t say the operator is to avoid assignment. The operator is to simplify nested calls. :slight_smile:

jeremyjh

jeremyjh

Isn’t nesting a means to avoid assignment? At least, assignment is the other alternative to nesting.

rvirding

rvirding OP

Creator of Erlang

One issue (problem) with the pipe is that in one way it hides what you are doing. Yes, you can see the actual operations being done but it can also hide what the actual data along the way is. Yes, you can add comments. However, using assignments means that you automatically do get information about what the actual data along the way is (at least if you use reasonable variable names).

I am not saying that you should avoid pipes and always use assignments, but I do think you can go too far with long pipe sequences.

This gets back to what I think is a very important question: for whom and why are you writing this code? Is it a quick hack which you don’t expect to have a long life? If it is for a product you envisage to be in use a long time which other people will maintain and develop then it is very important that you write clear, easily understandable and very explicit code. In this case maybe using judiciously using assignments can be a Good Thing™. I try to ask myself “in six months time will I understand what i have done here?” [*]

What I was really poking fun at was how far they had gone with the Kernel.- to be available to use a pipe.

[*] This also explains my opinion on having too many implicit default values which I can vent in a later post.

11
Post #8
sribe

sribe

Another point to consider: pipelines are quite clear when a new version of the same thing is being passed along to each function, but when the context of what is being passed changes midway through, that makes it hard to read. A Plug.Conn being passed through adding headers, setting status, body, sending, etc is the perfect example of a good use.

In your example, even though it’s a number being passed, what that number represents is different at each stage. And the fact that foo |> Kernel.-(bar) is vastly less clear than foo - bar means you’re starting off the pipeline with the very first step obscuring rather than clarifying.

yurko

yurko

That’s a good point, just recently in a test I moved the ending of the pipe into a separate call cause it made it unclear as to what the input is, so the whole test looked confusing despite the nice looking pipeline :slight_smile:

I still think the pipes are awesome, but they definitely can be abused.

Where Next? Top

Trending in Discussions Top

AstonJ
As the title says, please share what you’ve been up to with Elixir. Whether that’s been learning it, looking into it, making stuff with i...
2977 94592 917
New
cblavier
Hey there, It’s been more than a year since we started using LiveView as our main UI library and building a whole library of UI componen...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
heathen
Quite interesting article Google brought me. Didn’t find any mentions about it here. What do you think in general? Would you use togethe...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New
axelson
Hi there! :wave: @frigidcode and I (but mostly him) have been running an Elixir Book club, we’re almost done with Designing Elixir Syste...
New

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
georgeguimaraes
Just published claude-code-elixir, a plugin marketplace for Claude Code with Elixir support. These are the plugins I’ve been using for my...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews