ormolu
ormolu copied to clipboard
Formatting of "in" in let bindings
Why does it insert one additional whitespace before "in"? How to turn it off, to be 2 ones?
let a = 1 -- 2 whitespaces
b = 2
c = 3
in a + b + c -- 3 whitespaces
This way the expressions coming after in
start at an indentation level that is a multipiler of our indentation step, 2. There is no way to turn it off.
"in" = 3 + 1 whitespace +1st symbol of code = 5th symbol. Not a multiplier of 2.
Strange feature. Where is in Haskell code it also the case -- that "in" has the indentation of 3 whitespaces whereas "let" and everything else remain at 2 ones?
let a = 5
in a + 1
12345
a
starts at 5th column with indentation 4 (1234
bit, 4 characters), because we count columns from 1.
why not add whitespace after "in"?
let a = 5
in a + 1
12345
@mrkkrp can we reopen this? @GildedHonour is raising a point worth discussing. Putting an extra space before or after the in
is certainly unusual. I've never seen that style in any code before. It's also unusual in that every other element of Ormolu style means every line is indented by a multiple of 2 spaces, except for the in
in let-bindings.
I understand the justification you give for doing it this way. But there are plenty of other ways to do it, that don't force us into unfortunate exceptions. Furthermore, by your reasoning, if-then-else
would have to be indented specially too, so that the indentation level of the expression coming after each keyword is a multiple of 2. To wit,
- if the expression after the
in
is single-line, then what column it starts at is irrelevant. What matters is the indentation of the line, and that should be a multiple of 2 (unlike currently). - If the expression after the
in
is multi-line, then you don't need to have it start on the same line asin
. You can just as well have it start on the next line.
It can be instructive to look at the style that has been found to be effective in languages where people use let bindings far more frequently than in Haskell. These are far more frequent in OCaml, because there is no where
construct. They do this:
let x = 2 in
foo x baz
let f 1 = True
f n = False in
foo 2
But in the multi-line case, the following could work just as well:
let f 1 = True
f n = False
in
foo 2
or even
let
f 1 = True
f n = False
in
foo 2
Having the in
on the previous line serves them well because that way they can chain let
's. Their style guide includes a further justification: https://ocaml.org/learn/tutorials/guidelines.html#How-to-indent-let-in-constructs.
I never liked this style in OCaml because it is harder to see where the inner expression starts. They are almost forced to use this style because it is the only reasonable way to nest many let
s. OCaml programmers cannot introduce a let
with many bindings. We can. In fact, nested let
s are rare in Haskell, and I think this difference should be taken into account.
Also not a big fan of keeping in
on a separate line alone in case of multiline expressions. It somehow looks ugly to me, like a waste of vertical space or something. I think what we have right now is a reasonable compromise.
Stylistic battles are hard and exhausting.
I never liked this style in OCaml because it is harder to see where the inner expression starts.
By inner expression, do you mean whatever comes after the in
? That seems orthogonal to whether the in
goes on the previous line or not. Some OCaml code is written with the following variation:
let x = 2 in
foo x
(or even bigger levels of indentation)
Also not a big fan of keeping in on a separate line alone in case of multiline expressions. It somehow looks ugly to me, like a waste of vertical space or something.
Cannot argue with that either way. Haskell code is unusually dense relative to nearly every other language out there, and modern screens are massive. We can surely afford a few more lines here and there. Especially if it means a more predictable style. And all the more so if it's been tried and tested by thousands of projects over many years in another community.
The single space thing is so subtle and hard to see that I hadn't even noticed it. If it's hard to see how to be compliant with a formatter, that can be a problem.
FWIW personally I prefer the current style.
@jinwoo thank you. We'll talk about that with you sometime, one on one.
I also find this a rather idiosyncratic choice.
let x = 1
in x
is pretty much the only style I've ever seen in Haskell codebases that I've worked on (except those that now use ormolu
, of course :p ).