dotnet / fsharp

The F# compiler, F# core library, F# language service, and F# tooling integration for Visual Studio
https://dotnet.microsoft.com/languages/fsharp
MIT License
3.84k stars 776 forks source link

Investigate codegen-based "%A" format string #16663

Open vzarytovskii opened 5 months ago

vzarytovskii commented 5 months ago

printf and sprintf rely quite heavily on reflection when providing support for %A item formatting. And it is quite a chunk of FSharp.Core

We would like to remove that dependence to allow, trim to delivery smaller self contained programs and likely to make things perform a bit zoomier.

charlesroddie commented 5 months ago

To make this more manageable, the feature can be scoped to replacing the sprintfs that currently appear inside generated ToString() methods on DUs and records, when the user has not enabled --reflectionfree. This can be done relatively easily if you give up on carriage returns and spaces. For type DU = | A of B * C just return match du with | DU.A(b, c) -> $A({b}, {c}) and for type Record = { A: U; B: V } just return ${ A = {x.A}; B = {x.B} }.

Why?

Suppose the following things are done, which are high impact and lowish difficulty and so likely to happen before a large feature like this.

Then there is no reason to use printf etc. directly in user code.

vzarytovskii commented 5 months ago

To make this more manageable, the feature can be scoped to replacing the sprintfs that currently appear inside generated ToString() methods on DUs and records, when the user has not enabled --reflectionfree. This can be done relatively easily if you give up on carriage returns and spaces. For type DU = | A of B * C just return match du with | DU.A(b, c) -> $A({b}, {c}) and for type Record = { A: U; B: V } just return ${ A = {x.A}; B = {x.B} }.

Why?

Suppose the following things are done, which are high impact and lowish difficulty and so likely to happen before a large feature like this.

Then there is no reason to use printf etc. directly in user code.

All these are orthogonal to the current issue, we have not been planned any of those for .NET 9 and randomly picking those up will just jeopardise what we want to deliver.

This particular issue is about universal approach of how do we want to compile %A specifier, and do it via code generation instead of reflecting into custom objects.