You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/fsharp/style-guide/formatting.md
+72-62Lines changed: 72 additions & 62 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -102,6 +102,8 @@ For formatting XML doc comments, see "Formatting declarations" below.
102
102
103
103
## Formatting expressions
104
104
105
+
This section discusses formatting expressions of different kinds.
106
+
105
107
### Formatting string expressions
106
108
107
109
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 =
113
115
114
116
Multi-line interpolated expressions are discouraged. Instead, bind the expression result to a value and use that in the interpolated string.
115
117
116
-
## Formatting tuple expressions
118
+
###Formatting tuple expressions
117
119
118
120
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)`.
119
121
122
+
```fsharp
123
+
// OK
124
+
let pair = (1, 2)
125
+
let triples = [ (1, 2, 3); (11, 12, 13) ]
126
+
```
127
+
120
128
It is commonly accepted to omit parentheses in pattern matching of tuples:
121
129
122
130
```fsharp
@@ -143,7 +151,7 @@ let update model msg =
143
151
144
152
In summary, prefer parenthesized tuple instantiations, but when using tuples for pattern matching or a return value, it is considered fine to avoid parentheses.
145
153
146
-
## Formatting application expressions
154
+
###Formatting application expressions
147
155
148
156
When formatting a function or method application, arguments are provided on the same line when line-width allows:
149
157
@@ -470,7 +478,7 @@ x &&& y // Bitwise and, also for working with “flags” enumeration
470
478
x ^^^ y // Bitwise xor, also for working with “flags” enumeration
471
479
```
472
480
473
-
## Formatting if expressions
481
+
###Formatting if expressions
474
482
475
483
Indentation of conditionals depends on the size and complexity of the expressions that make them up.
476
484
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
518
526
```fsharp
519
527
if
520
528
complexExpression a b && env.IsDevelopment()
521
-
|| secondLongerExpression
522
-
aVeryLongparameterNameOne
523
-
aVeryLongparameterNameTwo
524
-
aVeryLongparameterNameThree then
529
+
|| someFunctionToCall
530
+
aVeryLongParameterNameOne
531
+
aVeryLongParameterNameTwo
532
+
aVeryLongParameterNameThree then
525
533
e1
526
534
else
527
535
e2
@@ -532,18 +540,18 @@ It is, however, better style to refactor long conditions to a let binding or sep
532
540
```fsharp
533
541
let performAction =
534
542
complexExpression a b && env.IsDevelopment()
535
-
|| secondLongerExpression
536
-
aVeryLongparameterNameOne
537
-
aVeryLongparameterNameTwo
538
-
aVeryLongparameterNameThree
543
+
|| someFunctionToCall
544
+
aVeryLongParameterNameOne
545
+
aVeryLongParameterNameTwo
546
+
aVeryLongParameterNameThree
539
547
540
548
if performAction then
541
549
e1
542
550
else
543
551
e2
544
552
```
545
553
546
-
## Formatting union case expressions
554
+
###Formatting union case expressions
547
555
548
556
Applying discriminated union cases follows the same rules as function and method applications.
549
557
That is, because the name is capitalized, code formatters will remove a space before a tuple:
@@ -567,7 +575,7 @@ let tree1 =
567
575
)
568
576
```
569
577
570
-
## Formatting list and array expressions
578
+
###Formatting list and array expressions
571
579
572
580
Write `x :: l` with spaces around the `::` operator (`::` is an infix operator, hence surrounded by spaces).
573
581
@@ -657,7 +665,7 @@ let daysOfWeek' includeWeekend =
657
665
658
666
In some cases, `do...yield` may aid in readability. These cases, though subjective, should be taken into consideration.
659
667
660
-
## Formatting record expressions
668
+
###Formatting record expressions
661
669
662
670
Short records can be written in one line:
663
671
@@ -696,7 +704,7 @@ let rainbow =
696
704
697
705
The same rules apply for list and array elements.
698
706
699
-
## Formatting copy-and-update record expressions
707
+
###Formatting copy-and-update record expressions
700
708
701
709
A copy-and-update record expression is still a record, so similar guidelines apply.
702
710
@@ -805,7 +813,7 @@ let rec sizeLambda acc =
805
813
| Var v -> succ acc
806
814
```
807
815
808
-
## Formatting try/with expressions
816
+
###Formatting try/with expressions
809
817
810
818
Pattern matching on the exception type should be indented at the same level as `with`.
811
819
@@ -900,7 +908,7 @@ let comparer =
900
908
901
909
## Formatting declarations
902
910
903
-
Top-level declarations should be documented and formatted consistently.
911
+
This section discusses formatting declarations of different kinds.
904
912
905
913
### Add blank lines between declarations
906
914
@@ -1108,7 +1116,7 @@ let (!>) x f = f x
1108
1116
1109
1117
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.
1110
1118
1111
-
## Formatting record declarations
1119
+
###Formatting record declarations
1112
1120
1113
1121
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:
1114
1122
@@ -1179,7 +1187,7 @@ type MyRecord =
1179
1187
interface IMyInterface
1180
1188
```
1181
1189
1182
-
## Formatting discriminated union declarations
1190
+
###Formatting discriminated union declarations
1183
1191
1184
1192
For discriminated union declarations, indent `|` in type definition by four spaces:
1185
1193
@@ -1253,7 +1261,7 @@ let MyUrl = "www.mywebsitethatiamworkingwith.com"
1253
1261
1254
1262
Avoid placing the attribute on the same line as the value.
1255
1263
1256
-
## Formatting module declarations
1264
+
###Formatting module declarations
1257
1265
1258
1266
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.
1259
1267
@@ -1330,8 +1338,51 @@ async {
1330
1338
}
1331
1339
```
1332
1340
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
+
1333
1382
## Formatting types and type annotations
1334
1383
1384
+
This section discusses formatting types and type annotations. This includes formatting signature files with the `.fsi` extension.
1385
+
1335
1386
### For types, prefer prefix syntax for generics (`Foo<T>`), with some specific exceptions
1336
1387
1337
1388
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() =
1399
1450
member _.SomeMethodBad(x: int): int = 1
1400
1451
```
1401
1452
1402
-
## Formatting types in signatures
1453
+
###Formatting types in signatures
1403
1454
1404
1455
When writing full function types in signatures, it is sometimes necessary to split the arguments
1405
1456
over multiple lines. For a tupled function the arguments are separated by `*`,
@@ -1561,44 +1612,3 @@ type MyRecord =
1561
1612
```
1562
1613
1563
1614
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