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/whats-new/fsharp-9.md
+33-31Lines changed: 33 additions & 31 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -11,11 +11,7 @@ F# 9 introduces a range of enhancements that make your programs safer, more resi
11
11
12
12
You can download the latest .NET SDK from the [.NET downloads page](https://dotnet.microsoft.com/download).
13
13
14
-
## F# language changes
15
-
16
-
This section describes updates to the language itself, changes you will notice when writing or reading F# code.
17
-
18
-
### Nullable reference types
14
+
## Nullable reference types
19
15
20
16
Although F# is designed to avoid `null`, it can creep in when interfacing with .NET libraries written in C#. F# now provides a type-safe way to deal with reference types that can have `null` as a valid value.
21
17
@@ -57,7 +53,7 @@ let findOrNull (index: int) (list: 'T list) : 'T | null when 'T : not struct =
57
53
| None -> null
58
54
```
59
55
60
-
###Discriminated union `.Is*` properties
56
+
## Discriminated union `.Is*` properties
61
57
62
58
Discriminated unions now have auto-generated properties for each case, allowing you to check if a value is of a particular case. For example, for the following type:
63
59
@@ -85,7 +81,7 @@ let canSendEmailTo person =
85
81
person.contact.IsEmail
86
82
```
87
83
88
-
###Partial active patterns can return `bool` instead of `unit option`
84
+
## Partial active patterns can return `bool` instead of `unit option`
89
85
90
86
Previously, partial active patterns returned `Some ()` to indicate a match and `None` otherwise. Now, they can also return `bool`.
###Prefer extension methods to intrinsic properties when arguments are provided
112
+
## Prefer extension methods to intrinsic properties when arguments are provided
117
113
118
114
To align with a pattern seen in some .NET libraries, where extension methods are defined with the same names as intrinsic properties of a type, F# now resolves these extension methods instead of failing the type check.
119
115
@@ -123,54 +119,60 @@ Example:
123
119
type Foo() =
124
120
member val X : int = 0 with get, set
125
121
126
-
[<Extension>]
122
+
[<Extension>]
127
123
type FooExt =
128
-
[<Extension>]
124
+
[<Extension>]
129
125
static member X (f: Foo, i: int) = f.X <- i; f
130
126
131
127
let f = Foo()
132
128
133
129
f.X(1) // We can now call the extension method to set the property and chain further calls
134
130
```
135
131
136
-
###Support for empty-bodied computation expressions
132
+
## Support for empty-bodied computation expressions
137
133
138
134
F# now supports empty [computation expressions](../language-reference/computation-expressions.md).
Writing an empty computation expression will result in a call to the CE builder's `Zero` method.
150
149
151
150
This is a more natural syntax compared to the previously available `builder { () }`.
152
151
153
-
### Hash directives are allowed to take non-string arguments
152
+
## Hash directives are allowed to take non-string arguments
154
153
155
154
Hash directives for the compiler previously only allowed string arguments passed in quotes. Now, they can take any type of argument.
156
155
157
156
Previously, you had:
158
157
```fsharp
159
158
#nowarn "0070"
160
-
#time "on"```
159
+
#time "on"
160
+
```
161
161
162
162
Now, you can write:
163
163
```fsharp
164
164
#nowarn 0070
165
-
#time on```
165
+
#time on
166
+
```
166
167
167
168
This also ties into the next two changes.
168
169
169
-
### Extended #help directive in fsi to show documentation in the REPL
170
+
## Extended #help directive in fsi to show documentation in the REPL
170
171
171
172
The `#help` directive in F# Interactive now shows documentation for a given object or function, which you can now pass without quotes.
172
173
173
-
<pre><code>> #help List.map;;
174
+
```
175
+
> #help List.map;;
174
176
175
177
Description:
176
178
Builds a new collection whose elements are the results of applying the given function
@@ -192,7 +194,7 @@ Full name: Microsoft.FSharp.Collections.ListModule.map
192
194
Assembly: FSharp.Core.dll
193
195
```
194
196
195
-
### Allow #nowarn to support the FS prefix on error codes to disable warnings
197
+
## Allow #nowarn to support the FS prefix on error codes to disable warnings
196
198
197
199
Previously, when you wanted to disable a warning and wrote `#nowarn "FS0057"`, you would get an `Invalid warning number 'FS0057'`. Even though the warning number is correct, it just wasn't supposed to have the `FS` prefix.
198
200
@@ -211,30 +213,30 @@ All of these will now work:
211
213
212
214
It's a good idea to use the same style throughout your project.
213
215
214
-
### Warning about TailCall attribute on non-rec functions or let-bound values
216
+
## Warning about TailCall attribute on non-rec functions or let-bound values
215
217
216
218
F# now emits a warning when you put the `[<TailCall>]` attribute somewhere it doesn't belong. While it has no effect on what the code does, it could confuse someone reading it.
217
219
218
220
For example, these usages will now emit a warning:
219
221
```fsharp
220
-
[<TailCall>]
222
+
[<TailCall>]
221
223
let someNonRecFun x = x + x
222
224
223
-
[<TailCall>]
225
+
[<TailCall>]
224
226
let someX = 23
225
227
226
-
[<TailCall>]
228
+
[<TailCall>]
227
229
let rec someRecLetBoundValue = nameof(someRecLetBoundValue)
228
230
```
229
231
230
-
### Enforce attribute targets
232
+
## Enforce attribute targets
231
233
232
234
The compiler now correctly enforces the `AttributeTargets` on let values, functions, union case declarations, implicit constructors, structs, and classes. This can prevent some hard-to-notice bugs, such as forgetting to add the unit argument to an Xunit test.
233
235
234
236
Previously, you could write:
235
237
236
238
```fsharp
237
-
[<Fact>]
239
+
[<Fact>]
238
240
let ``this test always fails`` =
239
241
Assert.True(false)
240
242
```
@@ -303,7 +305,7 @@ This constructor makes it easier to create a custom operation for a computation
303
305
304
306
```fsharp
305
307
type FooBuilder() =
306
-
[<CustomOperation>] // Previously had to be [<CustomOperation("bar")>]
308
+
[<CustomOperation>] // Previously had to be [<CustomOperation("bar")>]
307
309
member _.bar(state) = state
308
310
```
309
311
@@ -314,13 +316,13 @@ When using F# lists and sets from C#, you can now use collection expressions to
Collection expressions make it easier to use the F# immutable collections from C#. You might want to use the F# collections when you need their structural equality, which <xref:System.Collections.Immutable> collections don't have.
@@ -356,8 +358,8 @@ Now, there is an opt-in fix for this behavior available via the `--realsig+` com
356
358
357
359
```xml
358
360
<PropertyGroup>
359
-
<OtherFlags>--realsig+</OtherFlags>
360
-
</PropertyGroup>
361
+
<OtherFlags>--realsig+</OtherFlags>
362
+
</PropertyGroup>
361
363
```
362
364
363
365
## Performance improvements
@@ -369,7 +371,7 @@ Equality checks are now faster and allocate less memory.
0 commit comments