Skip to content
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

Longer quoted strings #1301

Open
6 tasks done
Happypig375 opened this issue Aug 5, 2023 · 3 comments
Open
6 tasks done

Longer quoted strings #1301

Happypig375 opened this issue Aug 5, 2023 · 3 comments

Comments

@Happypig375
Copy link
Contributor

Happypig375 commented Aug 5, 2023

I propose we add longer quoted strings (7+ quotes since 6 quotes specify an empty triple-quoted string) for when we need to embed source code that contains triple quoted strings. It is in line with C#'s design of raw string literals with variable length of starting quotes. Here, we can follow C#'s design of the multiline literal with the end delimiter specifying the indentation size (must be whitespaces, not any other character):

let fsharpCode = """""""
let string = $"""{String.replicate 3 "Hello World!\n"}"""
"""""""
let fsharpCode' = """""""
     let string = $"""{String.replicate 3 "Hello World!\n"}"""
     """""""
fsharpCode = fsharpCode' // true

The newlines directly next to the delimiters will not be included in the string. Therefore, the string has the following content without preceding or succeeding newlines:

let string = $"""{String.replicate 3 "Hello World!\n"}"""

Since 7 quotes are already quite long, we won't allow single-line versions of it. So these are illegal:

let fsharpCode = """""""let string = $"""{String.replicate 3 "Hello World!\n"}""" """"""" // error - no single line version
let fsharpCode' = """""""
     let string = $"""{String.replicate 3 "Hello World!\n"}""" """"""" // error - ending delimiter must be on its own line
let fsharpCode'' = """""""let
    string = $"""{String.replicate 3 "Hello World!\n"}"""
    """"""" // error - starting delimiter must be followed by a newline

The minimum lines that a longer quoted string must occupy is 3:

let empty = """""""
""""""" // error - too short - leave some space for adding content!
let empty' = """""""

""""""" // ok

This is because the starting delimiter requires a newline after, and the ending delimiter requires a newline before.

Interpolation will work:

let fsharpCode = $$"""""""
let string = $"""{String.replicate %%d{{3}} "Hello World!\n"}"""
"""""""

and produces the same string as before.
The existing way of approaching this problem in F# is to use runtime string manipulation which is less visually appealing and costs performance.

Pros and Cons

The advantages of making this adjustment to F# are

  1. Alignment with C#
  2. Convenience
  3. Visual appeal compared to triple quoted strings

The disadvantage of making this adjustment to F# is the learning complexity and implementation and maintenance costs.

Extra information

Estimated cost (XS, S, M, L, XL, XXL): S to M

Related suggestions:

Affidavit (please submit!)

Please tick these items by placing a cross in the box:

  • This is not a question (e.g. like one you might ask on StackOverflow) and I have searched StackOverflow for discussions of this issue
  • This is a language change and not purely a tooling change (e.g. compiler bug, editor support, warning/error messages, new warning, non-breaking optimisation) belonging to the compiler and tooling repository
  • This is not something which has obviously "already been decided" in previous versions of F#. If you're questioning a fundamental design decision that has obviously already been taken (e.g. "Make F# untyped") then please don't submit it
  • I have searched both open and closed suggestions on this site and believe this is not a duplicate

Please tick all that apply:

  • This is not a breaking change to the F# language design
  • I or my company would be willing to help implement and/or test this

For Readers

If you would like to see this issue implemented, please click the 👍 emoji on this issue. These counts are used to generally order the suggestions by engagement.

@Happypig375
Copy link
Contributor Author

Happypig375 commented Aug 6, 2023

We may also add language markers as specified in this C# proposal.

let mystr = """""""html
    <html>
        <body>
            <h1>Heading</h1>
            <p>Paragraph</p>
        </body>
    </html>
    """""""

@cr3wdayt5p
Copy link

This is a nice suggestion. We get the desirable feature of correct indentation for long strings while keeping the language backward compatible – and at 7 (or more) quotes the behavior is identical to C#.

F#:

let myStr =
    """""""
    <html>
        <body>
            <h1>Heading</h1>
            <p>Paragraph</p>
        </body>
    </html>
    """""""

C#:

var myStr =
    """""""
    <html>
        <body>
            <h1>Heading</h1>
            <p>Paragraph</p>
        </body>
    </html>
    """"""";

However I would suggest that this proposal is focused on nicely quoted strings, and that syntax highlighting is kept to a separate proposal that would work on all types of strings, e.g. standardize Rider's "language injection" feature:

let myStr1 =
    // lang=html
    "<b>hello</b>"

let myStr2 =
    // lang=html
    """<b>hello</b>"""

let myStr3 =
    // lang=html
    """""""
    <b>hello</b>
    """""""

@cr3wdayt5p
Copy link

I actually think this suggestion should be implemented solely due the readability benefit this would bring to the Fantomas test cases. Imagine how much nicer a file like this would read with correctly indented multiline strings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants