Skip to content

Commit 1c1389a

Browse files
committed
Add generic print and printn functions to FSharp.Core
Add inline `print: 'T -> unit` and `printn: 'T -> unit` to ExtraTopLevelOperators. These use the existing `string` function for conversion (InvariantCulture for IFormattable, .ToString() fallback) and write to Console.Out. RFC FS-1125
1 parent 7c7711b commit 1c1389a

9 files changed

Lines changed: 121 additions & 0 deletions

docs/release-notes/.FSharp.Core/10.0.300.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
### Added
1515

1616
* Add `List.partitionWith`, `Array.partitionWith`, `Set.partitionWith`, and `Array.Parallel.partitionWith` functions that partition a collection using a function that returns `Choice<'T1, 'T2>`. ([Language Suggestion #1119](https://github.com/fsharp/fslang-suggestions/issues/1119))
17+
* Added generic `print` and `printn` functions (`'T -> unit`) to `ExtraTopLevelOperators` for simple value printing to stdout. ([RFC FS-1125](https://github.com/fsharp/fslang-design/blob/main/RFCs/FS-1125-print-printn-functions.md), [PR #19265](https://github.com/dotnet/fsharp/pull/19265))
1718

1819
### Changed
1920

src/FSharp.Core/fslib-extra-pervasives.fs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,14 @@ module ExtraTopLevelOperators =
277277
let eprintfn format =
278278
Printf.eprintfn format
279279

280+
[<CompiledName("PrintValue")>]
281+
let inline print (value: 'T) =
282+
Console.Out.Write(string value)
283+
284+
[<CompiledName("PrintValueLine")>]
285+
let inline printn (value: 'T) =
286+
Console.Out.WriteLine(string value)
287+
280288
[<CompiledName("DefaultAsyncBuilder")>]
281289
let async = AsyncBuilder()
282290

src/FSharp.Core/fslib-extra-pervasives.fsi

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,33 @@ module ExtraTopLevelOperators =
5656
[<CompiledName("PrintFormatLineToError")>]
5757
val eprintfn: format: Printf.TextWriterFormat<'T> -> 'T
5858

59+
/// <summary>Converts the value to a string using the <c>string</c> operator and writes it to the standard output.</summary>
60+
///
61+
/// <param name="value">The value to print.</param>
62+
///
63+
/// <example id="print-example">
64+
/// <code lang="fsharp">
65+
/// print "Hello, "
66+
/// print "World!"
67+
/// // output: Hello, World!
68+
/// </code>
69+
/// </example>
70+
[<CompiledName("PrintValue")>]
71+
val inline print: value: 'T -> unit
72+
73+
/// <summary>Converts the value to a string using the <c>string</c> operator and writes it to the standard output, followed by a newline.</summary>
74+
///
75+
/// <param name="value">The value to print.</param>
76+
///
77+
/// <example id="printn-example">
78+
/// <code lang="fsharp">
79+
/// printn "Hello, World!"
80+
/// // output: Hello, World!
81+
/// </code>
82+
/// </example>
83+
[<CompiledName("PrintValueLine")>]
84+
val inline printn: value: 'T -> unit
85+
5986
/// <summary>Print to a string using the given format.</summary>
6087
///
6188
/// <param name="format">The formatter.</param>

tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.debug.bsl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,6 +1077,8 @@ Microsoft.FSharp.Core.ExtraTopLevelOperators: T PrintFormatToStringThenFail[T,TR
10771077
Microsoft.FSharp.Core.ExtraTopLevelOperators: T PrintFormatToString[T](Microsoft.FSharp.Core.PrintfFormat`4[T,Microsoft.FSharp.Core.Unit,System.String,System.String])
10781078
Microsoft.FSharp.Core.ExtraTopLevelOperators: T PrintFormatToTextWriter[T](System.IO.TextWriter, Microsoft.FSharp.Core.PrintfFormat`4[T,System.IO.TextWriter,Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Core.Unit])
10791079
Microsoft.FSharp.Core.ExtraTopLevelOperators: T PrintFormat[T](Microsoft.FSharp.Core.PrintfFormat`4[T,System.IO.TextWriter,Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Core.Unit])
1080+
Microsoft.FSharp.Core.ExtraTopLevelOperators: Void PrintValue[T](T)
1081+
Microsoft.FSharp.Core.ExtraTopLevelOperators: Void PrintValueLine[T](T)
10801082
Microsoft.FSharp.Core.ExtraTopLevelOperators: T SpliceExpression[T](Microsoft.FSharp.Quotations.FSharpExpr`1[T])
10811083
Microsoft.FSharp.Core.ExtraTopLevelOperators: T SpliceUntypedExpression[T](Microsoft.FSharp.Quotations.FSharpExpr)
10821084
Microsoft.FSharp.Core.ExtraTopLevelOperators: T[,] CreateArray2D[a,T](System.Collections.Generic.IEnumerable`1[a])

tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard20.release.bsl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,6 +1077,8 @@ Microsoft.FSharp.Core.ExtraTopLevelOperators: T PrintFormatToStringThenFail[T,TR
10771077
Microsoft.FSharp.Core.ExtraTopLevelOperators: T PrintFormatToString[T](Microsoft.FSharp.Core.PrintfFormat`4[T,Microsoft.FSharp.Core.Unit,System.String,System.String])
10781078
Microsoft.FSharp.Core.ExtraTopLevelOperators: T PrintFormatToTextWriter[T](System.IO.TextWriter, Microsoft.FSharp.Core.PrintfFormat`4[T,System.IO.TextWriter,Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Core.Unit])
10791079
Microsoft.FSharp.Core.ExtraTopLevelOperators: T PrintFormat[T](Microsoft.FSharp.Core.PrintfFormat`4[T,System.IO.TextWriter,Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Core.Unit])
1080+
Microsoft.FSharp.Core.ExtraTopLevelOperators: Void PrintValue[T](T)
1081+
Microsoft.FSharp.Core.ExtraTopLevelOperators: Void PrintValueLine[T](T)
10801082
Microsoft.FSharp.Core.ExtraTopLevelOperators: T SpliceExpression[T](Microsoft.FSharp.Quotations.FSharpExpr`1[T])
10811083
Microsoft.FSharp.Core.ExtraTopLevelOperators: T SpliceUntypedExpression[T](Microsoft.FSharp.Quotations.FSharpExpr)
10821084
Microsoft.FSharp.Core.ExtraTopLevelOperators: T[,] CreateArray2D[a,T](System.Collections.Generic.IEnumerable`1[a])

tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.debug.bsl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,6 +1080,8 @@ Microsoft.FSharp.Core.ExtraTopLevelOperators: T PrintFormatToStringThenFail[T,TR
10801080
Microsoft.FSharp.Core.ExtraTopLevelOperators: T PrintFormatToString[T](Microsoft.FSharp.Core.PrintfFormat`4[T,Microsoft.FSharp.Core.Unit,System.String,System.String])
10811081
Microsoft.FSharp.Core.ExtraTopLevelOperators: T PrintFormatToTextWriter[T](System.IO.TextWriter, Microsoft.FSharp.Core.PrintfFormat`4[T,System.IO.TextWriter,Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Core.Unit])
10821082
Microsoft.FSharp.Core.ExtraTopLevelOperators: T PrintFormat[T](Microsoft.FSharp.Core.PrintfFormat`4[T,System.IO.TextWriter,Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Core.Unit])
1083+
Microsoft.FSharp.Core.ExtraTopLevelOperators: Void PrintValue[T](T)
1084+
Microsoft.FSharp.Core.ExtraTopLevelOperators: Void PrintValueLine[T](T)
10831085
Microsoft.FSharp.Core.ExtraTopLevelOperators: T SpliceExpression[T](Microsoft.FSharp.Quotations.FSharpExpr`1[T])
10841086
Microsoft.FSharp.Core.ExtraTopLevelOperators: T SpliceUntypedExpression[T](Microsoft.FSharp.Quotations.FSharpExpr)
10851087
Microsoft.FSharp.Core.ExtraTopLevelOperators: T[,] CreateArray2D[a,T](System.Collections.Generic.IEnumerable`1[a])

tests/FSharp.Core.UnitTests/FSharp.Core.SurfaceArea.netstandard21.release.bsl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,6 +1080,8 @@ Microsoft.FSharp.Core.ExtraTopLevelOperators: T PrintFormatToStringThenFail[T,TR
10801080
Microsoft.FSharp.Core.ExtraTopLevelOperators: T PrintFormatToString[T](Microsoft.FSharp.Core.PrintfFormat`4[T,Microsoft.FSharp.Core.Unit,System.String,System.String])
10811081
Microsoft.FSharp.Core.ExtraTopLevelOperators: T PrintFormatToTextWriter[T](System.IO.TextWriter, Microsoft.FSharp.Core.PrintfFormat`4[T,System.IO.TextWriter,Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Core.Unit])
10821082
Microsoft.FSharp.Core.ExtraTopLevelOperators: T PrintFormat[T](Microsoft.FSharp.Core.PrintfFormat`4[T,System.IO.TextWriter,Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Core.Unit])
1083+
Microsoft.FSharp.Core.ExtraTopLevelOperators: Void PrintValue[T](T)
1084+
Microsoft.FSharp.Core.ExtraTopLevelOperators: Void PrintValueLine[T](T)
10831085
Microsoft.FSharp.Core.ExtraTopLevelOperators: T SpliceExpression[T](Microsoft.FSharp.Quotations.FSharpExpr`1[T])
10841086
Microsoft.FSharp.Core.ExtraTopLevelOperators: T SpliceUntypedExpression[T](Microsoft.FSharp.Quotations.FSharpExpr)
10851087
Microsoft.FSharp.Core.ExtraTopLevelOperators: T[,] CreateArray2D[a,T](System.Collections.Generic.IEnumerable`1[a])

tests/FSharp.Core.UnitTests/FSharp.Core.UnitTests.fsproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
<None Include="FSharp.Core\Microsoft.FSharp.Core\IntConversionsTestGenerator.fsx" />
7373
<Compile Include="FSharp.Core\Microsoft.FSharp.Core\OptionModule.fs" />
7474
<Compile Include="FSharp.Core\Microsoft.FSharp.Core\PrintfTests.fs" />
75+
<Compile Include="FSharp.Core\Microsoft.FSharp.Core\PrintTests.fs" />
7576
<Compile Include="FSharp.Core\Microsoft.FSharp.Core\ResultTests.fs" />
7677
<Compile Include="FSharp.Core\Microsoft.FSharp.Core\ExtraTopLevelOperatorsTests.fs" />
7778
<Compile Include="FSharp.Core\Microsoft.FSharp.Control\EventTypes.fs" />
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
2+
3+
// Various tests for:
4+
// Microsoft.FSharp.Core.ExtraTopLevelOperators.print
5+
// Microsoft.FSharp.Core.ExtraTopLevelOperators.printn
6+
7+
namespace FSharp.Core.UnitTests
8+
9+
open System
10+
open System.IO
11+
open Xunit
12+
13+
[<Collection(nameof FSharp.Test.NotThreadSafeResourceCollection)>]
14+
type PrintTests() =
15+
16+
let captureConsoleOut (f: unit -> unit) =
17+
let oldOut = Console.Out
18+
use sw = new StringWriter()
19+
Console.SetOut(sw)
20+
try
21+
f ()
22+
sw.ToString()
23+
finally
24+
Console.SetOut(oldOut)
25+
26+
[<Fact>]
27+
member _.``print writes string value``() =
28+
let result = captureConsoleOut (fun () -> print "hello")
29+
Assert.Equal("hello", result)
30+
31+
[<Fact>]
32+
member _.``print writes integer value``() =
33+
let result = captureConsoleOut (fun () -> print 42)
34+
Assert.Equal("42", result)
35+
36+
[<Fact>]
37+
member _.``print writes float with InvariantCulture``() =
38+
let result = captureConsoleOut (fun () -> print 3.14)
39+
Assert.Equal("3.14", result)
40+
41+
[<Fact>]
42+
member _.``print writes bool value``() =
43+
let result = captureConsoleOut (fun () -> print true)
44+
Assert.Equal("True", result)
45+
46+
[<Fact>]
47+
member _.``print writes Some value``() =
48+
let result = captureConsoleOut (fun () -> print (Some 42))
49+
Assert.Equal("Some(42)", result)
50+
51+
[<Fact>]
52+
member _.``print writes None value``() =
53+
let result = captureConsoleOut (fun () -> print None)
54+
Assert.Equal("", result)
55+
56+
[<Fact>]
57+
member _.``print writes list value``() =
58+
let result = captureConsoleOut (fun () -> print [1; 2; 3])
59+
Assert.Equal("[1; 2; 3]", result)
60+
61+
[<Fact>]
62+
member _.``printn writes value followed by newline``() =
63+
let result = captureConsoleOut (fun () -> printn "hello")
64+
Assert.Equal("hello" + Environment.NewLine, result)
65+
66+
[<Fact>]
67+
member _.``multiple prints concatenate``() =
68+
let result = captureConsoleOut (fun () ->
69+
print "Hello, "
70+
print "World!")
71+
Assert.Equal("Hello, World!", result)
72+
73+
[<Fact>]
74+
member _.``printn writes integer with newline``() =
75+
let result = captureConsoleOut (fun () -> printn 42)
76+
Assert.Equal("42" + Environment.NewLine, result)

0 commit comments

Comments
 (0)