-
Notifications
You must be signed in to change notification settings - Fork 830
Allow non-inline literals to be used as printf format #14670
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
T-Gro
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left minor comments, happy and approving already.
Out of curiosity (and definitely not needed to do if this does not work):
Since we:
- Can derive literals from other literals using basic arithmetical operators (at least for numbers)
- Can have non-inline literals in
printfn
Could we:
- Support
printfnfor a "+"-appended sequence of string literals?
i.e. having string-literal snippets, and reusing them togeher by the "+" operator.
In order to have better string-reuse of repeatable snippets.
Yeah, that would be nice. However, string constants aren't folded outside of specific contexts (attributes, literal definitions, ...), so a more general solution would perhaps be better. I think I've seen a conditional compilation directive that disables constant folding of certain kind somewhere? System.Console.WriteLine ("sadasd" + "Av")compiles to Console.WriteLine(string.Concat("sadasd", "Av"));whereas the C# compiler will concatenate the strings at compile time.
Interesting side-effect of these changes! While you can't concatenate the parts inline, you can still achieve reuse with a bit more verbosity let [<Literal>] coordinatesFormatSnippet = "(%f, %f, %f)"
let [<Literal>] playerPositionFormat = "Player is at " + coordinatesFormatSnippet
let [<Literal>] objectPositionFormat = "Object is at " + coordinatesFormatSnippet
let printPlayerPosition p =
printfn playerPositionFormat p.X p.Y p.ZIt would also be cool to support interpolation in this context, but that'd be straying a bit too far from the original suggestion. let [<Literal>] coordinatesFormatSnippet = "(%f, %f, %f)"
let printPlayerPosition p =
printfn $"Player is at {coordinatesFormatSnippet}" p.X p.Y p.Z |
The reuse example is already good, I like it. I think the next level to allow this inline would be a separate issue (not sure if this needs a lang suggestion or not) to "Treat inline + concatenation of any string literals as a string literal as well" , doing the concat already at the compiler. It does have downsides though - will increase binary codesize for keeping that combined string in, in exchange for 1 less allocation at runtime. |
|
Found a bug here, please don't merge. |
|
Ready now. |
Implements fsharp/fslang-suggestions#638, also extending it to IL constants, because why not.
I wanted to implement this as a type-directed conversion, but I wasn't sure whether I'd have to duplicate the logic from
TcFormatStringExprin MethodCalls.fs, because CheckExpressions is not available there. Since inline literal strings don't use this mechanism either, I chose the straightforward approach.