RFC: Extending Pipe

The main problem which prevents CapturePipe from (a) being included in Elixir proper and (b) from being used as a library in a more widespread fashion, is because of the relative precedence of & and |> (pipes are nested inside of captures), which for instance the Elixir Formatter does not handle it properly.

CapturePipe works as a macro which rewrites the AST after it has been parsed to alter the relative precedence of & and |>. The Elixir formatter runs before/without macros being expanded, so it will use the ‘as-written’ relative precedence of &, resulting in very odd indentation of the rest of the pipe.

The cleanest way to fix this would of course be in Elixir itself, but this would be a breaking change (and also there is no 100% consensus whether we want this). And as at least currently the Elixir formatter does not give us possibilities to ensure this case is handled properly in library-only code, we’re a bit stuck.

It’s not a ‘full’ dealbreaker since the problem does not happen when the capture is the last segment of the pipe. Thus CapturePipe is still very useful to e.g. pipe into a final &{:ok, &1}, which is rather common.
Still, it makes the library less idiomatic to use. And the alternative of not using the formatter is also a dealbreaker for many people.

As far as I remember there was no discussion on the forum about this whole ordeal, but there was an in-depth discussion on the Elixir-lang GitHub repository.

Tap and then were introduced in this elixir-lang-core mailing list thread and implemented as part as this issue on the Elixir-lang GitHub repository.
Indeed, this was the compromise to improve piping without needing any ‘hackery’.
Quoting @josevalim:

[…]
2. then receives an anonymous function, invokes it, and returns the result of the anonymous function. It will be how we can pipe to anonymous functions in Elixir. It is named andThen in Scala and known as then in many promise libraries across ecosystems.

I think this can improve the piping experience considerably while keeping things functional.

3 Likes