Skip to content

Commit 6abc4fb

Browse files
authored
Update formatting.md
1 parent 89a885a commit 6abc4fb

File tree

1 file changed

+72
-62
lines changed

1 file changed

+72
-62
lines changed

docs/fsharp/style-guide/formatting.md

Lines changed: 72 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ For formatting XML doc comments, see "Formatting declarations" below.
102102

103103
## Formatting expressions
104104

105+
This section discusses formatting expressions of different kinds.
106+
105107
### Formatting string expressions
106108

107109
String literals and interpolated strings can just be left on a single line, regardless of how long the line is.
@@ -113,10 +115,16 @@ let serviceStorageConnection =
113115

114116
Multi-line interpolated expressions are discouraged. Instead, bind the expression result to a value and use that in the interpolated string.
115117

116-
## Formatting tuple expressions
118+
### Formatting tuple expressions
117119

118120
A tuple instantiation should be parenthesized, and the delimiting commas within it should be followed by a single space, for example: `(1, 2)`, `(x, y, z)`.
119121

122+
```fsharp
123+
// OK
124+
let pair = (1, 2)
125+
let triples = [ (1, 2, 3); (11, 12, 13) ]
126+
```
127+
120128
It is commonly accepted to omit parentheses in pattern matching of tuples:
121129

122130
```fsharp
@@ -143,7 +151,7 @@ let update model msg =
143151

144152
In summary, prefer parenthesized tuple instantiations, but when using tuples for pattern matching or a return value, it is considered fine to avoid parentheses.
145153

146-
## Formatting application expressions
154+
### Formatting application expressions
147155

148156
When formatting a function or method application, arguments are provided on the same line when line-width allows:
149157

@@ -470,7 +478,7 @@ x &&& y // Bitwise and, also for working with “flags” enumeration
470478
x ^^^ y // Bitwise xor, also for working with “flags” enumeration
471479
```
472480

473-
## Formatting if expressions
481+
### Formatting if expressions
474482

475483
Indentation of conditionals depends on the size and complexity of the expressions that make them up.
476484
Write them on one line when:
@@ -518,10 +526,10 @@ If a condition is long, the `then` keyword is still placed at the end of the exp
518526
```fsharp
519527
if
520528
complexExpression a b && env.IsDevelopment()
521-
|| secondLongerExpression
522-
aVeryLongparameterNameOne
523-
aVeryLongparameterNameTwo
524-
aVeryLongparameterNameThree then
529+
|| someFunctionToCall
530+
aVeryLongParameterNameOne
531+
aVeryLongParameterNameTwo
532+
aVeryLongParameterNameThree then
525533
e1
526534
else
527535
e2
@@ -532,18 +540,18 @@ It is, however, better style to refactor long conditions to a let binding or sep
532540
```fsharp
533541
let performAction =
534542
complexExpression a b && env.IsDevelopment()
535-
|| secondLongerExpression
536-
aVeryLongparameterNameOne
537-
aVeryLongparameterNameTwo
538-
aVeryLongparameterNameThree
543+
|| someFunctionToCall
544+
aVeryLongParameterNameOne
545+
aVeryLongParameterNameTwo
546+
aVeryLongParameterNameThree
539547
540548
if performAction then
541549
e1
542550
else
543551
e2
544552
```
545553

546-
## Formatting union case expressions
554+
### Formatting union case expressions
547555

548556
Applying discriminated union cases follows the same rules as function and method applications.
549557
That is, because the name is capitalized, code formatters will remove a space before a tuple:
@@ -567,7 +575,7 @@ let tree1 =
567575
)
568576
```
569577

570-
## Formatting list and array expressions
578+
### Formatting list and array expressions
571579

572580
Write `x :: l` with spaces around the `::` operator (`::` is an infix operator, hence surrounded by spaces).
573581

@@ -657,7 +665,7 @@ let daysOfWeek' includeWeekend =
657665

658666
In some cases, `do...yield` may aid in readability. These cases, though subjective, should be taken into consideration.
659667

660-
## Formatting record expressions
668+
### Formatting record expressions
661669

662670
Short records can be written in one line:
663671

@@ -696,7 +704,7 @@ let rainbow =
696704

697705
The same rules apply for list and array elements.
698706

699-
## Formatting copy-and-update record expressions
707+
### Formatting copy-and-update record expressions
700708

701709
A copy-and-update record expression is still a record, so similar guidelines apply.
702710

@@ -805,7 +813,7 @@ let rec sizeLambda acc =
805813
| Var v -> succ acc
806814
```
807815

808-
## Formatting try/with expressions
816+
### Formatting try/with expressions
809817

810818
Pattern matching on the exception type should be indented at the same level as `with`.
811819

@@ -900,7 +908,7 @@ let comparer =
900908

901909
## Formatting declarations
902910

903-
Top-level declarations should be documented and formatted consistently.
911+
This section discusses formatting declarations of different kinds.
904912

905913
### Add blank lines between declarations
906914

@@ -1108,7 +1116,7 @@ let (!>) x f = f x
11081116

11091117
For any custom operator that starts with `*` and that has more than one character, you need to add a white space to the beginning of the definition to avoid a compiler ambiguity. Because of this, we recommend that you simply surround the definitions of all operators with a single white-space character.
11101118

1111-
## Formatting record declarations
1119+
### Formatting record declarations
11121120

11131121
For record declarations, indent `{` in type definition by four spaces, start the field list on the same line and align any members with the `{` token:
11141122

@@ -1179,7 +1187,7 @@ type MyRecord =
11791187
interface IMyInterface
11801188
```
11811189

1182-
## Formatting discriminated union declarations
1190+
### Formatting discriminated union declarations
11831191

11841192
For discriminated union declarations, indent `|` in type definition by four spaces:
11851193

@@ -1253,7 +1261,7 @@ let MyUrl = "www.mywebsitethatiamworkingwith.com"
12531261

12541262
Avoid placing the attribute on the same line as the value.
12551263

1256-
## Formatting module declarations
1264+
### Formatting module declarations
12571265

12581266
Code in a local module must be indented relative to the module, but code in a top-level module should not be indented. Namespace elements do not have to be indented.
12591267

@@ -1330,8 +1338,51 @@ async {
13301338
}
13311339
```
13321340

1341+
### Formatting computation expression operations
1342+
1343+
When creating custom operations for [computation expressions](../language-reference/computation-expressions.md), it is recommended to use camelCase naming:
1344+
1345+
```fsharp
1346+
type MathBuilder () =
1347+
member _.Yield _ = 0
1348+
1349+
[<CustomOperation("addOne")>]
1350+
member _.AddOne (state: int) =
1351+
state + 1
1352+
1353+
[<CustomOperation("subtractOne")>]
1354+
member _.SubtractOne (state: int) =
1355+
state - 1
1356+
1357+
[<CustomOperation("divideBy")>]
1358+
member _.DivideBy (state: int, divisor: int) =
1359+
state / divisor
1360+
1361+
[<CustomOperation("multiplyBy")>]
1362+
member _.MultiplyBy (state: int, factor: int) =
1363+
state * factor
1364+
1365+
let math = MathBuilder()
1366+
1367+
// 10
1368+
let myNumber =
1369+
math {
1370+
addOne
1371+
addOne
1372+
addOne
1373+
subtractOne
1374+
divideBy 2
1375+
multiplyBy 10
1376+
}
1377+
```
1378+
1379+
The domain that's being modeled should ultimately drive the naming convention.
1380+
If it is idiomatic to use a different convention, that convention should be used instead.
1381+
13331382
## Formatting types and type annotations
13341383

1384+
This section discusses formatting types and type annotations. This includes formatting signature files with the `.fsi` extension.
1385+
13351386
### For types, prefer prefix syntax for generics (`Foo<T>`), with some specific exceptions
13361387

13371388
F# allows both postfix style of writing generic types (for example, `int list`) as well as the prefix style (for example, `list<int>`).
@@ -1399,7 +1450,7 @@ type C() =
13991450
member _.SomeMethodBad(x: int): int = 1
14001451
```
14011452

1402-
## Formatting types in signatures
1453+
### Formatting types in signatures
14031454

14041455
When writing full function types in signatures, it is sometimes necessary to split the arguments
14051456
over multiple lines. For a tupled function the arguments are separated by `*`,
@@ -1561,44 +1612,3 @@ type MyRecord =
15611612
```
15621613

15631614
When applied to a parameter, they must be on the same line and separated by a `;` separator.
1564-
1565-
## Formatting computation expression operations
1566-
1567-
When creating custom operations for [computation expressions](../language-reference/computation-expressions.md), it is recommended to use camelCase naming:
1568-
1569-
```fsharp
1570-
type MathBuilder () =
1571-
member _.Yield _ = 0
1572-
1573-
[<CustomOperation("addOne")>]
1574-
member _.AddOne (state: int) =
1575-
state + 1
1576-
1577-
[<CustomOperation("subtractOne")>]
1578-
member _.SubtractOne (state: int) =
1579-
state - 1
1580-
1581-
[<CustomOperation("divideBy")>]
1582-
member _.DivideBy (state: int, divisor: int) =
1583-
state / divisor
1584-
1585-
[<CustomOperation("multiplyBy")>]
1586-
member _.MultiplyBy (state: int, factor: int) =
1587-
state * factor
1588-
1589-
let math = MathBuilder()
1590-
1591-
// 10
1592-
let myNumber =
1593-
math {
1594-
addOne
1595-
addOne
1596-
addOne
1597-
subtractOne
1598-
divideBy 2
1599-
multiplyBy 10
1600-
}
1601-
```
1602-
1603-
The domain that's being modeled should ultimately drive the naming convention.
1604-
If it is idiomatic to use a different convention, that convention should be used instead.

0 commit comments

Comments
 (0)