Skip to content

Commit c00b32e

Browse files
committed
Add generic print and println functions to FSharp.Core
Add inline `print: 'T -> unit` and `println: '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 cb4bfe4 commit c00b32e

9 files changed

Lines changed: 122 additions & 0 deletions

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
### Added
44

5+
* Added generic `print` and `println` 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))
6+
57
### Changed
68

79
* Added complexity documentation (Big-O notation) to all 462 functions across Array, List, Seq, Map, and Set collection modules. ([PR #19240](https://github.com/dotnet/fsharp/pull/19240))

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 println (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="println-example">
78+
/// <code lang="fsharp">
79+
/// println "Hello, World!"
80+
/// // output: Hello, World!
81+
/// </code>
82+
/// </example>
83+
[<CompiledName("PrintValueLine")>]
84+
val inline println: 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
@@ -1073,6 +1073,8 @@ Microsoft.FSharp.Core.ExtraTopLevelOperators: T PrintFormatToStringThenFail[T,TR
10731073
Microsoft.FSharp.Core.ExtraTopLevelOperators: T PrintFormatToString[T](Microsoft.FSharp.Core.PrintfFormat`4[T,Microsoft.FSharp.Core.Unit,System.String,System.String])
10741074
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])
10751075
Microsoft.FSharp.Core.ExtraTopLevelOperators: T PrintFormat[T](Microsoft.FSharp.Core.PrintfFormat`4[T,System.IO.TextWriter,Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Core.Unit])
1076+
Microsoft.FSharp.Core.ExtraTopLevelOperators: Void PrintValue[T](T)
1077+
Microsoft.FSharp.Core.ExtraTopLevelOperators: Void PrintValueLine[T](T)
10761078
Microsoft.FSharp.Core.ExtraTopLevelOperators: T SpliceExpression[T](Microsoft.FSharp.Quotations.FSharpExpr`1[T])
10771079
Microsoft.FSharp.Core.ExtraTopLevelOperators: T SpliceUntypedExpression[T](Microsoft.FSharp.Quotations.FSharpExpr)
10781080
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
@@ -1073,6 +1073,8 @@ Microsoft.FSharp.Core.ExtraTopLevelOperators: T PrintFormatToStringThenFail[T,TR
10731073
Microsoft.FSharp.Core.ExtraTopLevelOperators: T PrintFormatToString[T](Microsoft.FSharp.Core.PrintfFormat`4[T,Microsoft.FSharp.Core.Unit,System.String,System.String])
10741074
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])
10751075
Microsoft.FSharp.Core.ExtraTopLevelOperators: T PrintFormat[T](Microsoft.FSharp.Core.PrintfFormat`4[T,System.IO.TextWriter,Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Core.Unit])
1076+
Microsoft.FSharp.Core.ExtraTopLevelOperators: Void PrintValue[T](T)
1077+
Microsoft.FSharp.Core.ExtraTopLevelOperators: Void PrintValueLine[T](T)
10761078
Microsoft.FSharp.Core.ExtraTopLevelOperators: T SpliceExpression[T](Microsoft.FSharp.Quotations.FSharpExpr`1[T])
10771079
Microsoft.FSharp.Core.ExtraTopLevelOperators: T SpliceUntypedExpression[T](Microsoft.FSharp.Quotations.FSharpExpr)
10781080
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
@@ -1076,6 +1076,8 @@ Microsoft.FSharp.Core.ExtraTopLevelOperators: T PrintFormatToStringThenFail[T,TR
10761076
Microsoft.FSharp.Core.ExtraTopLevelOperators: T PrintFormatToString[T](Microsoft.FSharp.Core.PrintfFormat`4[T,Microsoft.FSharp.Core.Unit,System.String,System.String])
10771077
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])
10781078
Microsoft.FSharp.Core.ExtraTopLevelOperators: T PrintFormat[T](Microsoft.FSharp.Core.PrintfFormat`4[T,System.IO.TextWriter,Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Core.Unit])
1079+
Microsoft.FSharp.Core.ExtraTopLevelOperators: Void PrintValue[T](T)
1080+
Microsoft.FSharp.Core.ExtraTopLevelOperators: Void PrintValueLine[T](T)
10791081
Microsoft.FSharp.Core.ExtraTopLevelOperators: T SpliceExpression[T](Microsoft.FSharp.Quotations.FSharpExpr`1[T])
10801082
Microsoft.FSharp.Core.ExtraTopLevelOperators: T SpliceUntypedExpression[T](Microsoft.FSharp.Quotations.FSharpExpr)
10811083
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
@@ -1076,6 +1076,8 @@ Microsoft.FSharp.Core.ExtraTopLevelOperators: T PrintFormatToStringThenFail[T,TR
10761076
Microsoft.FSharp.Core.ExtraTopLevelOperators: T PrintFormatToString[T](Microsoft.FSharp.Core.PrintfFormat`4[T,Microsoft.FSharp.Core.Unit,System.String,System.String])
10771077
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])
10781078
Microsoft.FSharp.Core.ExtraTopLevelOperators: T PrintFormat[T](Microsoft.FSharp.Core.PrintfFormat`4[T,System.IO.TextWriter,Microsoft.FSharp.Core.Unit,Microsoft.FSharp.Core.Unit])
1079+
Microsoft.FSharp.Core.ExtraTopLevelOperators: Void PrintValue[T](T)
1080+
Microsoft.FSharp.Core.ExtraTopLevelOperators: Void PrintValueLine[T](T)
10791081
Microsoft.FSharp.Core.ExtraTopLevelOperators: T SpliceExpression[T](Microsoft.FSharp.Quotations.FSharpExpr`1[T])
10801082
Microsoft.FSharp.Core.ExtraTopLevelOperators: T SpliceUntypedExpression[T](Microsoft.FSharp.Quotations.FSharpExpr)
10811083
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
@@ -73,6 +73,7 @@
7373
<None Include="FSharp.Core\Microsoft.FSharp.Core\IntConversionsTestGenerator.fsx" />
7474
<Compile Include="FSharp.Core\Microsoft.FSharp.Core\OptionModule.fs" />
7575
<Compile Include="FSharp.Core\Microsoft.FSharp.Core\PrintfTests.fs" />
76+
<Compile Include="FSharp.Core\Microsoft.FSharp.Core\PrintTests.fs" />
7677
<Compile Include="FSharp.Core\Microsoft.FSharp.Core\ResultTests.fs" />
7778
<Compile Include="FSharp.Core\Microsoft.FSharp.Core\ExtraTopLevelOperatorsTests.fs" />
7879
<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.println
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 _.``println writes value followed by newline``() =
63+
let result = captureConsoleOut (fun () -> println "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 _.``println writes integer with newline``() =
75+
let result = captureConsoleOut (fun () -> println 42)
76+
Assert.Equal("42" + Environment.NewLine, result)

0 commit comments

Comments
 (0)