Skip to content

Commit abf85dd

Browse files
committed
change blog-style code blocks to regular
1 parent 20c29b7 commit abf85dd

File tree

1 file changed

+74
-50
lines changed

1 file changed

+74
-50
lines changed

docs/fsharp/whats-new/fsharp-9.md

Lines changed: 74 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ For more details, watch out for an [upcoming blog post about this feature](https
2323

2424
Here are some examples:
2525

26-
<pre><code class="language-fsharp">// Declared type at let-binding
26+
```fsharp
27+
// Declared type at let-binding
2728
let notAValue: string | null = null
2829
2930
let isAValue: string | null = "hello world"
@@ -54,64 +55,71 @@ let findOrNull (index: int) (list: 'T list) : 'T | null when 'T : not struct =
5455
match List.tryItem index list with
5556
| Some item -> item
5657
| None -> null
57-
</code></pre>
58+
```
5859

5960
### Discriminated union `.Is*` properties
6061

6162
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:
6263

63-
<pre><code class="language-fsharp">type Contact =
64+
```fsharp
65+
type Contact =
6466
| Email of address: string
6567
| Phone of countryCode: int * number: string
6668
6769
type Person = { name: string; contact: Contact }
68-
</code></pre>
70+
```
6971

7072
Previously, you would have to write something like:
7173

72-
<pre><code class="language-fsharp">let canSendEmailTo person =
74+
```fsharp
75+
let canSendEmailTo person =
7376
match person.contact with
7477
| Email _ -> true
7578
| _ -> false
76-
</code></pre>
79+
```
7780

7881
Now, you can instead write:
7982

80-
<pre><code class="language-fsharp">let canSendEmailTo person =
83+
```fsharp
84+
let canSendEmailTo person =
8185
person.contact.IsEmail
82-
</code></pre>
86+
```
8387

8488
### Partial active patterns can return `bool` instead of `unit option`
8589

8690
Previously, partial active patterns would return `Some ()` to indicate a match and `None` otherwise. Now, they can also return `bool`.
8791

8892
For example, the active pattern for the following:
89-
<pre><code class="language-fsharp">match key with
93+
```fsharp
94+
match key with
9095
| CaseInsensitive "foo" -> ...
9196
| CaseInsensitive "bar" -> ...
92-
</code></pre>
97+
```
9398

9499
Would previously be written as:
95-
<pre><code class="language-fsharp">let (|CaseInsensitive|_|) (pattern: string) (value: string) =
100+
```fsharp
101+
let (|CaseInsensitive|_|) (pattern: string) (value: string) =
96102
if String.Equals(value, pattern, StringComparison.OrdinalIgnoreCase) then
97103
Some ()
98104
else
99105
None
100-
</code></pre>
106+
```
101107

102108
Now, you can instead write:
103109

104-
<pre><code class="language-fsharp">let (|CaseInsensitive|_|) (pattern: string) (value: string) =
110+
```fsharp
111+
let (|CaseInsensitive|_|) (pattern: string) (value: string) =
105112
String.Equals(value, pattern, StringComparison.OrdinalIgnoreCase)
106-
</code></pre>
113+
```
107114

108115
### Prefer extension methods to intrinsic properties when arguments are provided
109116

110117
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.
111118

112119
Example:
113120

114-
<pre><code class="language-fsharp">type Foo() =
121+
```fsharp
122+
type Foo() =
115123
member val X : int = 0 with get, set
116124
117125
[&ltExtension&gt;]
@@ -122,19 +130,20 @@ type FooExt =
122130
let f = Foo()
123131
124132
f.X(1) // We can now call the extension method to set the property and chain further calls
125-
</code></pre>
133+
```
126134

127135
### Support for empty-bodied computation expressions
128136

129137
F# now supports empty [computation expressions](https://learn.microsoft.com/dotnet/fsharp/language-reference/computation-expressions).
130138

131-
<pre class="language-fsharp"><code>let xs = seq { } // Empty sequence</code></pre>
139+
<pre class="language-fsharp"><code>let xs = seq { } // Empty sequence```
132140

133-
<pre><code class="language-fsharp">let html =
141+
```fsharp
142+
let html =
134143
div {
135144
p { "Some content." }
136145
p { } // Empty paragraph
137-
}</code></pre>
146+
}```
138147

139148
Writing an empty computation expression will result in a call to the CE builder's `Zero` method.
140149

@@ -145,12 +154,14 @@ This is a more natural syntax compared to the previously available `builder { ()
145154
Hash directives for the compiler previously only allowed string arguments passed in quotes. Now, they can take any type of argument.
146155

147156
Previously, you had:
148-
<pre><code class="language-fsharp">#nowarn "0070"
149-
#time "on"</code></pre>
157+
```fsharp
158+
#nowarn "0070"
159+
#time "on"```
150160

151161
Now, you can write:
152-
<pre><code class="language-fsharp">#nowarn 0070
153-
#time on</code></pre>
162+
```fsharp
163+
#nowarn 0070
164+
#time on```
154165

155166
This also ties into the next two changes.
156167

@@ -178,7 +189,7 @@ inputs |> List.map (fun x -> x.Length)
178189

179190
Full name: Microsoft.FSharp.Collections.ListModule.map
180191
Assembly: FSharp.Core.dll
181-
</code></pre>
192+
```
182193

183194
### Allow #nowarn to support the FS prefix on error codes to disable warnings
184195

@@ -187,14 +198,15 @@ Previously, when you wanted to disable a warning and wrote `#nowarn "FS0057"`, y
187198
Now, you won't have to spend time figuring that out because the warning numbers are accepted even with the prefix.
188199

189200
All of these will now work:
190-
<pre><code class="language-fsharp">#nowarn 57
201+
```fsharp
202+
#nowarn 57
191203
#nowarn 0057
192204
#nowarn FS0057
193205

194206
#nowarn "57"
195207
#nowarn "0057"
196208
#nowarn "FS0057"
197-
</code></pre>
209+
```
198210

199211
It's probably a good idea to stick to the same style throughout your project.
200212

@@ -203,26 +215,28 @@ It's probably a good idea to stick to the same style throughout your project.
203215
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.
204216

205217
For example, these will now emit a warning:
206-
<pre><code class="language-fsharp">[&lt;TailCall&gt;]
218+
```fsharp
219+
[&lt;TailCall&gt;]
207220
let someNonRecFun x = x + x
208221

209222
[&lt;TailCall&gt;]
210223
let someX = 23
211224

212225
[&lt;TailCall&gt;]
213226
let rec someRecLetBoundValue = nameof(someRecLetBoundValue)
214-
</code></pre>
227+
```
215228

216229
### Enforce attribute targets
217230

218231
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.
219232

220233
Previously, you could have written:
221234

222-
<pre><code class="language-fsharp">[&lt;Fact&gt;]
235+
```fsharp
236+
[&lt;Fact&gt;]
223237
let ``this test always fails`` =
224238
Assert.True(false)
225-
</code></pre>
239+
```
226240

227241
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.
228242

@@ -246,46 +260,51 @@ There are four functions (each with three variants) available:
246260

247261
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.
248262

249-
<pre><code class="language-fsharp">let allPlayers = [ "Alice"; "Bob"; "Charlie"; "Dave" ]
263+
```fsharp
264+
let allPlayers = [ "Alice"; "Bob"; "Charlie"; "Dave" ]
250265
let round1Order = allPlayers |> List.randomShuffle // [ "Charlie"; "Dave"; "Alice"; "Bob" ]
251-
</code></pre>
266+
```
252267

253268
For arrays, there are also `InPlace` variants that shuffle the array in place.
254269

255270
#### Choice
256271

257272
The choice functions return a single random element from the given collection. The random choice is weighted evenly on the size of the collection.
258273

259-
<pre><code class="language-fsharp">let allPlayers = [ "Alice"; "Bob"; "Charlie"; "Dave" ]
274+
```fsharp
275+
let allPlayers = [ "Alice"; "Bob"; "Charlie"; "Dave" ]
260276
let randomPlayer = allPlayers |> List.randomChoice // "Charlie"
261-
</code></pre>
277+
```
262278

263279
#### Choices
264280

265281
Choices select N elements from the input collection in random order, allowing elements to be selected more than once.
266282

267-
<pre><code class="language-fsharp">let weather = [ "Raining"; "Sunny"; "Snowing"; "Windy" ]
283+
```fsharp
284+
let weather = [ "Raining"; "Sunny"; "Snowing"; "Windy" ]
268285
let forecastForNext3Days = weather |> List.randomChoices 3 // [ "Windy"; "Snowing"; "Windy" ]
269-
</code></pre>
286+
```
270287

271288
#### Sample
272289

273290
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.
274291

275-
<pre><code class="language-fsharp">let foods = [ "Apple"; "Banana"; "Carrot"; "Donut"; "Egg" ]
292+
```fsharp
293+
let foods = [ "Apple"; "Banana"; "Carrot"; "Donut"; "Egg" ]
276294
let today'sMenu = foods |> List.randomSample 3 // [ "Donut"; "Apple"; "Egg" ]
277-
</code></pre>
295+
```
278296

279297
For a full list of functions and their variants, see ([RFC #1135](https://github.com/fsharp/fslang-design/blob/main/RFCs/FS-1135-random-functions-for-collections.md)).
280298

281299
### Parameterless constructor for `CustomOperationAttribute`
282300

283301
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).
284302

285-
<pre><code class="language-fsharp">type FooBuilder() =
303+
```fsharp
304+
type FooBuilder() =
286305
[&lt;CustomOperation&gt;] // Previously would have to be [&lt;CustomOperation("bar")&gt;]
287306
member _.bar(state) = state
288-
</code></pre>
307+
```
289308

290309
### C# collection expression support for F# lists and sets
291310

@@ -294,12 +313,12 @@ When using F# lists and sets from C#, you can now use collection expressions to
294313
Instead of:
295314

296315
<pre><code class="language-csharp">FSharpSet&lt;int&gt; mySet = SetModule.FromArray([1, 2, 3]);
297-
</code></pre>
316+
```
298317

299318
You can now write:
300319

301320
<pre><code class="language-csharp">FSharpSet&lt;int&gt; mySet = [ 1, 2, 3 ];
302-
</code></pre>
321+
```
303322

304323
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.
305324

@@ -334,7 +353,7 @@ Now, there is an opt-in fix for this behavior available via the `--realsig+` com
334353
<pre><code class="language-xml">&lt;PropertyGroup&gt;
335354
&lt;OtherFlags&gt;--realsig+&lt;/OtherFlags&gt;
336355
&lt;/PropertyGroup&gt;
337-
</code></pre>
356+
```
338357

339358
## Performance improvements
340359

@@ -344,7 +363,8 @@ Equality checks are now faster and allocate less memory.
344363

345364
For example:
346365

347-
<pre><code class="language-fsharp">[&lt;Struct&gt;]
366+
```fsharp
367+
[&lt;Struct&gt;]
348368
type MyId =
349369
val Id: int
350370
new id = { Id = id }
@@ -353,7 +373,7 @@ let ids = Array.init 1000 MyId
353373
let missingId = MyId -1
354374

355375
// used to box 1000 times, doesn't box anymore
356-
let _ = ids |> Array.contains missingId</code></pre>
376+
let _ = ids |> Array.contains missingId```
357377

358378
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/).
359379

@@ -367,15 +387,18 @@ The compiler now generates optimized code for more instances of `start..finish`
367387

368388
This leads to anywhere from 1.25× up to 8× speed up in loops:
369389

370-
<pre><code class="language-fsharp">for … in start..finish do …</code></pre>
390+
```fsharp
391+
for … in start..finish do …```
371392

372393
List/array expressions:
373394

374-
<pre><code class="language-fsharp">[start..step..finish]</code></pre>
395+
```fsharp
396+
[start..step..finish]```
375397

376398
and comprehensions:
377399

378-
<pre><code class="language-fsharp">[for n in start..finish -> f n]</code></pre>
400+
```fsharp
401+
[for n in start..finish -> f n]```
379402

380403
### Optimized `for x in xs -> …` in list and array comprehensions
381404

@@ -392,8 +415,9 @@ This previously opt-in feature has been thoroughly tested and is now enabled by
392415
Sometimes extra parentheses are used for clarity, but sometimes they are just noise. For the latter case, you now get a code fix in Visual Studio to remove them.
393416

394417
For example:
395-
<pre><code class="language-fsharp">let f (x) = x // -> let f x = x
396-
let _ = (2 * 2) + 3 // -> let _ = 2 * 2 + 3</code></pre>
418+
```fsharp
419+
let f (x) = x // -> let f x = x
420+
let _ = (2 * 2) + 3 // -> let _ = 2 * 2 + 3```
397421

398422
### Custom Visualizer support for F# in Visual Studio
399423

0 commit comments

Comments
 (0)