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
### Prefer extension methods to intrinsic properties when arguments are provided
116
117
117
-
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# will now resolve these extension methods instead of failing the type check.
118
+
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.
118
119
119
120
Example:
120
121
@@ -134,7 +135,7 @@ f.X(1) // We can now call the extension method to set the property and chain fur
134
135
135
136
### Support for empty-bodied computation expressions
136
137
137
-
F# now supports empty [computation expressions](https://learn.microsoft.com/dotnet/fsharp/language-reference/computation-expressions).
138
+
F# now supports empty [computation expressions](../language-reference/computation-expressions.md).
It's probably a good idea to stick to the same style throughout your project.
212
+
It's a good idea to use the same style throughout your project.
212
213
213
214
### Warning about TailCall attribute on non-rec functions or let-bound values
214
215
215
-
F# will now emit 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.
216
+
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.
216
217
217
-
For example, these will now emit a warning:
218
+
For example, these usages will now emit a warning:
218
219
```fsharp
219
220
[<TailCall>]
220
221
let someNonRecFun x = x + x
@@ -230,15 +231,15 @@ let rec someRecLetBoundValue = nameof(someRecLetBoundValue)
230
231
231
232
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.
232
233
233
-
Previously, you could have written:
234
+
Previously, you could write:
234
235
235
236
```fsharp
236
237
[<Fact>]
237
238
let ``this test always fails`` =
238
239
Assert.True(false)
239
240
```
240
241
241
-
Run the tests with `dotnet test` and they would pass. Since the test function is not actually a function, it is ignored by the test runner.
242
+
When you ran the tests with `dotnet test`, they would pass. Since the test function is not actually a function, it was ignored by the test runner.
242
243
243
244
Now, with correct attribute enforcement, you will get an `error FS0842: This attribute is not valid for use on this language element`.
244
245
@@ -248,17 +249,17 @@ Now, with correct attribute enforcement, you will get an `error FS0842: This att
248
249
249
250
The `List`, `Array`, and `Seq` modules have new functions for random sampling and shuffling. This makes F# easier to use for common data science, machine learning, game development, and other scenarios where randomness is needed.
250
251
251
-
All functions have variants using:
252
+
All functions have the following variants:
252
253
253
-
* An implicit thread-safe shared [`Random`](https://learn.microsoft.com/dotnet/api/system.random) instance
254
-
* Taking a `Random` instance as an argument
255
-
* Taking a custom `randomizer` function, which should return a float value greater than or equal to 0.0 and less than 1.0
254
+
* One that uses an implicit, thread-safe, shared <xref:System.Random> instance
255
+
* One that takes a `Random` instance as an argument
256
+
* One that takes a custom `randomizer` function, which should return a float value greater than or equal to 0.0 and less than 1.0
256
257
257
-
There are four functions (each with three variants) available:
258
+
There are four functions (each with three variants) available: `Shuffle`, `Choice`, `Choices`, and `Sample`.
258
259
259
260
#### Shuffle
260
261
261
-
The shuffle functions return a new collection of the same type and size, with each item in a randomly mixed position. The chance to end up in any position is weighted evenly on the length of the collection.
262
+
The `Shuffle` functions return a new collection of the same type and size, with each item in a randomly mixed position. The chance to end up in any position is weighted evenly on the length of the collection.
262
263
263
264
```fsharp
264
265
let allPlayers = [ "Alice"; "Bob"; "Charlie"; "Dave" ]
@@ -269,7 +270,7 @@ For arrays, there are also `InPlace` variants that shuffle the array in place.
269
270
270
271
#### Choice
271
272
272
-
The choice functions return a single random element from the given collection. The random choice is weighted evenly on the size of the collection.
273
+
The `Choice` functions return a single random element from the given collection. The random choice is weighted evenly on the size of the collection.
273
274
274
275
```fsharp
275
276
let allPlayers = [ "Alice"; "Bob"; "Charlie"; "Dave" ]
Sample selects N elements from the input collection in random order, without allowing elements to be selected more than once. N cannot be greater than the collection length.
291
+
The `Sample` functions select N elements from the input collection in random order, without allowing elements to be selected more than once. N cannot be greater than the collection length.
291
292
292
293
```fsharp
293
294
let foods = [ "Apple"; "Banana"; "Carrot"; "Donut"; "Egg" ]
@@ -298,11 +299,11 @@ For a full list of functions and their variants, see ([RFC #1135](https://github
298
299
299
300
### Parameterless constructor for `CustomOperationAttribute`
300
301
301
-
This makes it easier to create a custom operation for a computation expression builder. It will use the name of the method instead of having to explicitly name it (when in most cases the name matches the method name already).
302
+
This constructor makes it easier to create a custom operation for a computation expression builder. It uses the name of the method instead of having to explicitly name it (when in most cases the name matches the method name already).
302
303
303
304
```fsharp
304
305
type FooBuilder() =
305
-
[<CustomOperation>] // Previously would have to be [<CustomOperation("bar")>]
306
+
[<CustomOperation>] // Previously had to be [<CustomOperation("bar")>]
306
307
member _.bar(state) = state
307
308
```
308
309
@@ -312,21 +313,23 @@ When using F# lists and sets from C#, you can now use collection expressions to
This makes it easier to use the F# immutable collections from C#, for example when you need their structural equality, which `System.Collections.Immutable` collections don't have.
326
+
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.
324
327
325
328
## Quality of life improvements
326
329
327
330
### Parser recovery
328
331
329
-
There have been continuous improvements in parser recovery, meaning that tooling (e.g. syntax highlighting) still works with code when you're in the middle of editing it and it may not be syntactically correct at all times.
332
+
There have been continuous improvements in parser recovery, meaning that tooling (for example, syntax highlighting) still works with code when you're in the middle of editing it and it might not be syntactically correct at all times.
330
333
331
334
For example, the parser will now recover on unfinished `as` patterns, object expressions, enum case declarations, record declarations, complex primary constructor patterns, unresolved long identifiers, empty match clauses, missing union case fields, and missing union case field types.
332
335
@@ -335,22 +338,24 @@ For example, the parser will now recover on unfinished `as` patterns, object exp
335
338
Diagnostics, or understanding what the compiler doesn't like about your code, are an important part of the user experience with F#. There are a number of new or improved diagnostic messages or more precise diagnostic locations in F# 9.
336
339
337
340
These include:
341
+
338
342
- Ambiguous override method in object expression
339
343
- Abstract members when used in non-abstract classes
340
-
- When a property has the same name as a discriminated union case
344
+
- Property that has the same name as a discriminated union case
341
345
- Active pattern argument count mismatch
342
346
- Unions with duplicated fields
343
347
- Using `use!` with `and!` in computation expressions
344
348
345
-
There is also a new compile-time error for classes with over 65,520 methods in generated [IL](https://learn.microsoft.com/dotnet/standard/managed-code#intermediate-language--execution). Such classes won't be loadable by the CLR and would result in a runtime error. (Not that you would ever really want to have so many methods, but there have been cases with generated code.)
349
+
There is also a new compile-time error for classes with over 65,520 methods in generated [IL](../../standard/managed-code.md#intermediate-language--execution). Such classes aren't loadable by the CLR and would result in a run-time error. (Not that you would ever really want to have so many methods, but there have been cases with generated code.)
346
350
347
351
### Real visibility
348
352
349
-
There is a quirk with how F# generates assemblies that results in private members being written to [IL](https://learn.microsoft.com/dotnet/standard/managed-code#intermediate-language--execution) as internal. This allows inappropriate access to private members from non-F# projects that have access to an F# project via [`InternalsVisibleTo`](https://learn.microsoft.com/dotnet/api/system.runtime.compilerservices.internalsvisibletoattribute).
353
+
There is a quirk with how F# generates assemblies that results in private members being written to [IL](../../standard/managed-code.md#intermediate-language--execution) as internal. This allows inappropriate access to private members from non-F# projects that have access to an F# project via [`InternalsVisibleTo`](xref:System.Runtime.CompilerServices.InternalsVisibleToAttribute).
350
354
351
355
Now, there is an opt-in fix for this behavior available via the `--realsig+` compiler flag. Try it in your solution to see if any of your projects depend on this behavior. You can add it to your `.fsproj` files like this:
@@ -373,7 +378,8 @@ let ids = Array.init 1000 MyId
373
378
let missingId = MyId -1
374
379
375
380
// used to box 1000 times, doesn't box anymore
376
-
let _ = ids |> Array.contains missingId```
381
+
let _ = ids |> Array.contains missingId
382
+
```
377
383
378
384
You can read all the details here: [F# Developer Stories: How we’ve finally fixed a 9-year-old performance issue](https://devblogs.microsoft.com/dotnet/fsharp-developer-stories-how-weve-finally-fixed-a-9yearold-performance-issue/).
379
385
@@ -388,17 +394,20 @@ The compiler now generates optimized code for more instances of `start..finish`
388
394
This leads to anywhere from 1.25× up to 8× speed up in loops:
389
395
390
396
```fsharp
391
-
for … in start..finish do …```
397
+
for … in start..finish do …
398
+
```
392
399
393
400
List/array expressions:
394
401
395
402
```fsharp
396
-
[start..step..finish]```
403
+
[start..step..finish]
404
+
```
397
405
398
406
and comprehensions:
399
407
400
408
```fsharp
401
-
[for n in start..finish -> f n]```
409
+
[for n in start..finish -> f n]
410
+
```
402
411
403
412
### Optimized `for x in xs -> …` in list and array comprehensions
404
413
@@ -417,16 +426,17 @@ Sometimes extra parentheses are used for clarity, but sometimes they are just no
417
426
For example:
418
427
```fsharp
419
428
let f (x) = x // -> let f x = x
420
-
let _ = (2 * 2) + 3 // -> let _ = 2 * 2 + 3```
429
+
let _ = (2 * 2) + 3 // -> let _ = 2 * 2 + 3
430
+
```
421
431
422
-
### Custom Visualizer support for F# in Visual Studio
432
+
### Custom visualizer support for F# in Visual Studio
423
433
424
434
The debugger visualizer in Visual Studio now works with F# projects.
Previously, no signature help was offered in a situation like the following, where a function in the middle of a pipeline already had a complex curried parameter (e.g., a lambda) applied to it. Now, the signature tooltip will show up for the next parameter (`state`):
440
+
Previously, no signature help was offered in a situation like the following, where a function in the middle of a pipeline already had a complex curried parameter (for example, a lambda) applied to it. Now, the signature tooltip shows up for the next parameter (`state`):
0 commit comments