Skip to content

Conversation

@kerams
Copy link
Contributor

@kerams kerams commented Jan 27, 2023

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 TcFormatStringExpr in MethodCalls.fs, because CheckExpressions is not available there. Since inline literal strings don't use this mechanism either, I chose the straightforward approach.

@kerams kerams requested a review from a team as a code owner January 27, 2023 21:27
Copy link
Member

@T-Gro T-Gro left a 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 printfn for 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.

@kerams
Copy link
Contributor Author

kerams commented Feb 1, 2023

Support printfn for a "+"-appended sequence of string literals?

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.

i.e. having string-literal snippets, and reusing them togeher by the "+" operator.

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.Z

It 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

@T-Gro
Copy link
Member

T-Gro commented Feb 2, 2023

Support printfn for a "+"-appended sequence of string literals?

Yeah, that would be nice.

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.
(unless there is codebase which massively "+"s string literals into various combinations, it should not be noticeable of course)

@kerams
Copy link
Contributor Author

kerams commented Feb 11, 2023

Found a bug here, please don't merge.

@kerams
Copy link
Contributor Author

kerams commented Feb 12, 2023

Ready now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

6 participants