should |> be indented by the formatter? Here are two alternative ways to format it: (using this as an example)
jsonNumArray =
jsonNum
|> sepBy (scalar ',')
|> between (scalar '[') (scalar ']')
jsonNumArray =
jsonNum
|> sepBy (scalar ',')
|> between (scalar '[') (scalar ']')
The first way (no indentation) is how F# formats it and also how Elixir formats it.
Elm indents it, but I happen to know that that's because when elm-format was originally created, infix operators were a userspace thing and it treated them all the same (so it would indent both |> and + the same way, because they're both arbitrary infix operators)
I can see some pros and cons to either
Personally, I find the first formatting easier to read
Despite being used to indenting |> I think I'd prefer the first example as well.
two reasons that lead me to rethink whether defaulting to the way Elm does it is correct here (as Roc frequently does!) are:
jsonNumArray =
it
|> sepBy (scalar ',')
|> between (scalar '[') (scalar ']')
jsonNumArray =
it
|> sepBy (scalar ',')
|> between (scalar '[') (scalar ']')
I think if we do that, we should definitely automatically insert a blank line after the pipeline in defs
e.g. the formatter shouldn't permit this:
jsonNumArray =
x = foo
|> sepBy (scalar ',')
|> between (scalar '[') (scalar ']')
y = bar
|> sepBy (scalar ',')
|> between (scalar '[') (scalar ']')
baz x y
instead, it should reformat to:
jsonNumArray =
x = foo
|> sepBy (scalar ',')
|> between (scalar '[') (scalar ']')
y = bar
|> sepBy (scalar ',')
|> between (scalar '[') (scalar ']')
baz x y
or perhaps even:
jsonNumArray =
x =
foo
|> sepBy (scalar ',')
|> between (scalar '[') (scalar ']')
y =
bar
|> sepBy (scalar ',')
|> between (scalar '[') (scalar ']')
baz x y
Richard Feldman said:
or perhaps even:
jsonNumArray = x = foo |> sepBy (scalar ',') |> between (scalar '[') (scalar ']') y = bar |> sepBy (scalar ',') |> between (scalar '[') (scalar ']') baz x y
I think this example looks best
a related question is whether other infix operators should be indented the same way
for example, this could be formatted as either:
if
(byte >= 97 && byte <= 122) # lowercase ASCII
|| (byte >= 65 && byte <= 90) # uppercase ASCII
|| (byte >= 48 && byte <= 57) # digit
then
or
if
(byte >= 97 && byte <= 122) # lowercase ASCII
|| (byte >= 65 && byte <= 90) # uppercase ASCII
|| (byte >= 48 && byte <= 57) # digit
then
and same with +, -, etc.
once again, I can see arguments either way! :big_smile:
I could go either way on those. Though maybe for consistency with |> other operators shouldn't be indented either?
an interesting argument for not indenting |> that just occurred to me: the operator works differently in Roc and Elm (in Roc it pipes the first argument; in Elm it pipes the last argument), so having a visual distinction if you're working in a code base that has both Roc and Elm code could be a nice reminder of which one you're dealing with!
Do F# and Elixir pipe the first argument?
Roc and Elixir do it the same way, and F# and Elm do it the same way
I like where this thread is going :)
F# and Elm do it that way because of currying
and Roc and Elixir aren't curried, so there are advantages to doing it the other way
I think this example looks best
This is also what is done in Elixir/ the Elixir formatter.
Last updated: Jun 16 2026 at 16:19 UTC