FormattingDecisionCommas.md

November 3, 2020 ยท View on GitHub

Formatting Decision: Commas in Lists

This is a document explaining our reasoning behind the formatting decision for commas in lists.

The most polarizing issue about lists is whether you prefer to have , (commas) as a suffix for the expression on each line:

[
  x,
  y,
  z
]

Or is if you prefer to have a , character as a prefix of the expression on each line:

[ x
, y
, z
]

We have decided to try and settle this issue using an analysis of what is more popular in the practice.

Analysis

Our analysis is very naive and we hope it is good enough, but we are open to contributions for a more sophisticated analysis. We have decided to analyse the OTP and WhatsApp code base, since this was too big code bases we had access to.

We grep .hrl and .erl files recursively. This requires grepping for two patterns:

  1. lists with commas at the end of the line (suffixes)
  2. lists with commas at the start of the line (prefixes)

Suffix Pattern

Here are examples of the suffix pattern.

One that starts with a newline after the opening bracket:

[
  a,
...

One that has no newline after the opening bracket:

[ a/1,
...

The Suffix pattern:

  • starts with open bracket (\[), followed by
  • optional white space (\s)*, followed by
  • optional an new line (\n)?, followed by
  • optional white space (\s)*, again followed by
  • characters that are not a comma, close bracket, new line or opening call or opening record or tuple ([^,\n\]\{\(])*, followed by
  • a comma and some optional white space before the new line ,(\s*)\n

So we end up with the following pcregrep pattern, where:

  • -M allows us to match over multiple lines.
  • grep "\[" allows us to only count once per list
pcregrep --include=".*\.erl" --include=".*\.hrl" -rM "(\[)(\s)*(\n)?(\s)*([^,\n\]\{\(])*,(\s*)\n" . | grep "\[" | wc -l

Prefix Pattern

One that ends with a newline before the closing bracket:

...
  , a
]

One that has no newline before the closing bracket:

...
, a/1 ]

The Prefix Pattern:

  • starts with a newline, followed by some white space and a comma. (\n(\s)*,), followed by
  • characters that are not a comma, closing bracket, new line or opening bracket ([^,\n\]\[])*, followed by
  • an optional newline (\n)?, followed by
  • some white space (\s)*
  • and ending with a closing bracket (\])

So we end up with the following pcregrep pattern, where:

  • -M allows us to match over multiple lines.
  • grep "\]" allows us to only count once per list
pcregrep --include=".*\.erl" --include=".*\.hrl" -rM "(\n(\s)*,)([^,\n\]\[])*(\n)?(\s)*(\])" . | grep "\]" | wc -l

Result

We found that both OTP and WhatsApp prefer commas as a suffix.

OTP:

  • Commas as a Suffix: 4533
  • Commas as a Prefix: 20

WhatsApp:

  • Commas as a Suffix: 50x
  • Commas as a Prefix: x

Kazoo:

  • Commas as a Suffix: 124
  • Commas as a Prefix: 3116

MongooseIM:

  • Commas as a Suffix: 852
  • Commas as a Prefix: 1

ejabberd:

  • Commas as a Suffix: 173
  • Commas as a Prefix: 0

inaka repos:

  • Commas as a Suffix: 244
  • Commas as a Prefix: 442

We tried some other code bases too: luerl and circuitbreak, but these data sets where too small in comparison.

Welcoming to new comers

Another consideration is possibly alienating new comers. We would love to attract more talent to the erlang community.

The following style guides from other languages use ending commas exclusively:

Decision

The issue seems to be divisive per erlang code base, but still the numbers show that commas at the end of lines are more popular. erlfmt will try to enforce this as the consistent style.