[Accepted] SE-0168: Multi-Line String Literals

Yes.

I suggest people who want to hard wrap long strings literals to write a new proposal, on top of SE-0168 which has been accepted now.

Try to convince the community and the core team that there is a significant problem that needs to be addressed, and that your solution is the good one.

Gwendal

···

Le 22 avr. 2017 à 22:58, Thorsten Seitz via swift-evolution <swift-evolution@swift.org> a écrit :

You seem to be choosing to deliberately ignore what I (and others) write.

Sure, I can give an example. I'm not going to suggest that it'd win any
awards, but:

By restricting multiline literals to begin and end on distinct lines, the
core team has established an interesting property. Namely, "literals" are
delimited horizontally while """literals""" are delimited vertically.

To enable hard wrapping, permit continuation of literals by apposition of
consecutive literals. That is, "Hello, " "world!" would be equivalent to
"Hello, world!". This single rule can be applied to either kind of string
literal. That is:

let a =
"Hello, "
"world!"

let b =
"""
Hello,
""" """
world!
"""

a == b // true

It certainly permits elided newlines. It is the exact same rule applied to
both types of literals. It preserves code indentation and does not require
single-line string literals to support code stripping. I leave it to your
judgement whether it works "equally well" and/or is "horrible."

···

On Sun, Apr 23, 2017 at 04:13 Brent Royal-Gordon <brent@architechies.com> wrote:

On Apr 22, 2017, at 8:12 AM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Sat, Apr 22, 2017 at 3:38 AM, Brent Royal-Gordon < > brent@architechies.com> wrote:

On Apr 21, 2017, at 11:48 AM, Xiaodi Wu via swift-evolution < >> swift-evolution@swift.org> wrote:

This goes to my question to David Hart. Isn't this an argument for a
feature to allow breaking a single-line string literal across multiple
lines? What makes this a use case for some feature for _multiline_ string
literals in particular?

Well, if you're breaking a string across several lines, you will want
indentation stripping too. Are you suggesting we should also bring that
feature to single-line string literals with escaped newlines?

No, I am suggesting that whatever design is used for escaped newlines, if
at all possible it should be equally apt for "strings" and """strings"""
such that it will not require indentation stripping.

Could you share an example of such a design? It doesn't have to be
something you'd be happy to have in the language; it just needs to fit the
following criteria:

* Permits non-significant hard-wrapping in a string literal.

* Works equally well with single and triple string literals.

* Preserves code indentation, but does not require single string literals
to do indentation stripping.

* Is not horribly inconvenient.

--
Brent Royal-Gordon
Architechies

Hmm, I can see that Wux already replied to this question but let me give another more or less obvious answer which I believe has come up in a shape or another already:

No, I am suggesting that whatever design is used for escaped newlines, if at all possible it should be equally apt for "strings" and """strings""" such that it will not require indentation stripping.

Could you share an example of such a design?

One way to achieve the criteria below for both singly and triply quoted strings would be to borrow the repeated opening quote syntax (from earlier discussions) for singly quoted strings:

    let s1 = "abc\
              "def\n\
              "ghi \
              "xyz"
    assert(s1 == "abcdef\nghi xyz")
    
    let s2 = "abc\
             "def\n\
    /* Leading white space, */ "ghi \
    // as well as comments
    
    // and empty lines in between are
    // insignificant when it comes to singly
    // quoted literals.
        "xyz"
    assert(s2 == s1)
    
    let s3 = """
        abc\
        def
        ghi \
        xyz
        """
    assert(s3 == s1)

The criteria:

* Permits non-significant hard-wrapping in a string literal.

:white_check_mark: The string continues from the position of the backslash, with no extra space or line break inserted.

* Works equally well with single and triple string literals.

:white_check_mark: In both cases, a trailing `\` has the same meaning. In singly quoted strings, the only way to insert a newline is by quoting (`\n`), as it always was.

* Preserves code indentation, but does not require single string literals to do indentation stripping.

:white_check_mark: The indentation is just more explicit with singly quoted string literals.

* Is not horribly inconvenient.

:man_shrugging: Depends who you ask, I guess, but I think not horrible. And, after all, the programmer is free to choose between two quoting styles with different trade offs.

* * *

One thing that remains to be defined is whether trailing space is allowed (and ignored) after the backslash or not (and thus an error). I initially thought it's best to make into a compiler error, just like the indenting white space of the triple quoted string literals.

OTOH, we could also allow inline comments after the backslash:

    let whyNot = "this, \
        "that, \ // <- Oxford comma
        "and stuff"
    assert(whyNot == "this, that, and stuff")
    
    let list = """
        - this,
        - that,\n\// comment using "Adrian's \n\"
        - and stuff
        """
    assert(list == "- this,\n- that,\n- and stuff")

[Nit: If comments after the backslash were allowed, we'd need to either require a space after the backslash (e.g. `\ //`), or else accept as string continuation / comment start markers both `\//` (until newline) and `\/*` (until `*/`), as seen in the latter example above.]

I find this design — with or without comments — would naturally allow the programmer to choose between precision (singly quoted) and convenience/legibility (triply quoted). And of course it would allow breaking long string literals to multiple lines in a consistent way, which, for triply quoted strings, is also lighter than just concatenating with `+`.

— Pyry

PS. I also slightly regret that SE-0168 ended up stripping the trailing newline, because multiline strings seem to compose (concatenate) better with a trailing newline there by default. But I understand if the inconvenience of `print(str, terminator: "")` weighed more than the other option.

···

Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org> wrote:

Following this thread it reads to me that SE-0168 being accepted without newline escapes was
regrettable as it gave us more flexibility in formatting “long strings”.

As the core team rejected it on the basis that it was inconsistent with conventional string literals the
obvious thing to do is raise a short micro-proposal that newline escape be introduced into both. This
would also bring them into line with C literals. I’ve drafted a new proposal we could discuss and which
I hope to submit tomorrow as the implementation is trivial if it’s not too late:

https://github.com/johnno1962c/swift-evolution/blob/master/proposals/0173-newline-escape-in-strings.md

For me personally, this would also have the happy side effect of making it possible to reopen the debate
about "should the final newline be stripped by default" as it could now so easily be escaped for those who
like their multiline literals missing a newline on the last line :)

I’ve updated the prototype toolchain to bring it into line with the Core team's decision available here:

http://johnholdsworth.com/swift-LOCAL-2017-04-22-a-osx.tar.gz

(This includes newline escaping on all strings but dutifully strips the last line)

As it looks like this patch might form the basis of the implementation in Swift 4, all testing appreciated.

-John

···

On 23 Apr 2017, at 10:41, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

Sure, I can give an example. I'm not going to suggest that it'd win any awards, but:

By restricting multiline literals to begin and end on distinct lines, the core team has established an interesting property. Namely, "literals" are delimited horizontally while """literals""" are delimited vertically.

To enable hard wrapping, permit continuation of literals by apposition of consecutive literals. That is, "Hello, " "world!" would be equivalent to "Hello, world!". This single rule can be applied to either kind of string literal. That is:

let a =
"Hello, "
"world!"

let b =
"""
Hello,
""" """
world!
"""

a == b // true

It certainly permits elided newlines. It is the exact same rule applied to both types of literals. It preserves code indentation and does not require single-line string literals to support code stripping. I leave it to your judgement whether it works "equally well" and/or is "horrible."
On Sun, Apr 23, 2017 at 04:13 Brent Royal-Gordon <brent@architechies.com <mailto:brent@architechies.com>> wrote:

On Apr 22, 2017, at 8:12 AM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Sat, Apr 22, 2017 at 3:38 AM, Brent Royal-Gordon <brent@architechies.com <mailto:brent@architechies.com>> wrote:

On Apr 21, 2017, at 11:48 AM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

This goes to my question to David Hart. Isn't this an argument for a feature to allow breaking a single-line string literal across multiple lines? What makes this a use case for some feature for _multiline_ string literals in particular?

Well, if you're breaking a string across several lines, you will want indentation stripping too. Are you suggesting we should also bring that feature to single-line string literals with escaped newlines?

No, I am suggesting that whatever design is used for escaped newlines, if at all possible it should be equally apt for "strings" and """strings""" such that it will not require indentation stripping.

Could you share an example of such a design? It doesn't have to be something you'd be happy to have in the language; it just needs to fit the following criteria:

* Permits non-significant hard-wrapping in a string literal.

* Works equally well with single and triple string literals.

* Preserves code indentation, but does not require single string literals to do indentation stripping.

* Is not horribly inconvenient.

--
Brent Royal-Gordon
Architechies

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

The main issue with that design is, even if it’s only bikeshedding here, that it creates ambiguity.

let a =
"Hello, "
"world!"
To me that reads like the string constant a would contain "Hello, " and the literal "world!" sits somewhere in the middle of your code and is unused. Nothing signals to the developer that both string will be concatenated during compile time.

···

--
Adrian Zubarev
Sent with Airmail

Am 23. April 2017 um 11:41:38, Xiaodi Wu via swift-evolution (swift-evolution@swift.org) schrieb:

Sure, I can give an example. I'm not going to suggest that it'd win any awards, but:

By restricting multiline literals to begin and end on distinct lines, the core team has established an interesting property. Namely, "literals" are delimited horizontally while """literals""" are delimited vertically.

To enable hard wrapping, permit continuation of literals by apposition of consecutive literals. That is, "Hello, " "world!" would be equivalent to "Hello, world!". This single rule can be applied to either kind of string literal. That is:

let a =
"Hello, "
"world!"

let b =
"""
Hello,
""" """
world!
"""

a == b // true

It certainly permits elided newlines. It is the exact same rule applied to both types of literals. It preserves code indentation and does not require single-line string literals to support code stripping. I leave it to your judgement whether it works "equally well" and/or is "horrible."
On Sun, Apr 23, 2017 at 04:13 Brent Royal-Gordon <brent@architechies.com> wrote:
On Apr 22, 2017, at 8:12 AM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Sat, Apr 22, 2017 at 3:38 AM, Brent Royal-Gordon <brent@architechies.com> wrote:
On Apr 21, 2017, at 11:48 AM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

This goes to my question to David Hart. Isn't this an argument for a feature to allow breaking a single-line string literal across multiple lines? What makes this a use case for some feature for _multiline_ string literals in particular?

Well, if you're breaking a string across several lines, you will want indentation stripping too. Are you suggesting we should also bring that feature to single-line string literals with escaped newlines?

No, I am suggesting that whatever design is used for escaped newlines, if at all possible it should be equally apt for "strings" and """strings""" such that it will not require indentation stripping.

Could you share an example of such a design? It doesn't have to be something you'd be happy to have in the language; it just needs to fit the following criteria:

* Permits non-significant hard-wrapping in a string literal.

* Works equally well with single and triple string literals.

* Preserves code indentation, but does not require single string literals to do indentation stripping.

* Is not horribly inconvenient.

--
Brent Royal-Gordon
Architechies

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

I’ve never thought about allowing hard wrapping from single quoted string literals until it come up during the latest discussion.

At first glance I don’t have anything against it. I wouldn’t put comments into the mix for now, to keep things simple. (I’ve already asked about comments, but the community rejected the idea _for now_.)

What was the exact use case for hard wrapping for the single quoted literals again? (Again I’m not against it.) Actually I believe I pitched a very similar design in the discussion thread (not during the review).

···

--
Adrian Zubarev
Sent with Airmail

Am 23. April 2017 um 13:14:35, Pyry Jahkola via swift-evolution (swift-evolution@swift.org) schrieb:

Hmm, I can see that Wux already replied to this question but let me give another more or less obvious answer which I believe has come up in a shape or another already:

Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org> wrote:

No, I am suggesting that whatever design is used for escaped newlines, if at all possible it should be equally apt for "strings" and """strings""" such that it will not require indentation stripping.

Could you share an example of such a design?

One way to achieve the criteria below for both singly and triply quoted strings would be to borrow the repeated opening quote syntax (from earlier discussions) for singly quoted strings:

let s1 = &quot;abc\\
          &quot;def\\n\\
          &quot;ghi \\
          &quot;xyz&quot;
assert\(s1 == &quot;abcdef\\nghi xyz&quot;\)

let s2 = &quot;abc\\
         &quot;def\\n\\
/\* Leading white space, \*/ &quot;ghi \\
// as well as comments

// and empty lines in between are
// insignificant when it comes to singly
// quoted literals\.
    &quot;xyz&quot;
assert\(s2 == s1\)

let s3 = &quot;&quot;&quot;
    abc\\
    def
    ghi \\
    xyz
    &quot;&quot;&quot;
assert\(s3 == s1\)

The criteria:

* Permits non-significant hard-wrapping in a string literal.

:white_check_mark: The string continues from the position of the backslash, with no extra space or line break inserted.

* Works equally well with single and triple string literals.

:white_check_mark: In both cases, a trailing `\` has the same meaning. In singly quoted strings, the only way to insert a newline is by quoting (`\n`), as it always was.

* Preserves code indentation, but does not require single string literals to do indentation stripping.

:white_check_mark: The indentation is just more explicit with singly quoted string literals.

* Is not horribly inconvenient.

:man_shrugging: Depends who you ask, I guess, but I think not horrible. And, after all, the programmer is free to choose between two quoting styles with different trade offs.

* * *

One thing that remains to be defined is whether trailing space is allowed (and ignored) after the backslash or not (and thus an error). I initially thought it's best to make into a compiler error, just like the indenting white space of the triple quoted string literals.

OTOH, we could also allow inline comments after the backslash:

let whyNot = &quot;this, \\
    &quot;that, \\ // &lt;\- Oxford comma
    &quot;and stuff&quot;
assert\(whyNot == &quot;this, that, and stuff&quot;\)

let list = &quot;&quot;&quot;
    \- this,
    \- that,\\n\\// comment using &quot;Adrian&#39;s \\n\\&quot;
    \- and stuff
    &quot;&quot;&quot;
assert\(list == &quot;\- this,\\n\- that,\\n\- and stuff&quot;\)

[Nit: If comments after the backslash were allowed, we'd need to either require a space after the backslash (e.g. `\ //`), or else accept as string continuation / comment start markers both `\//` (until newline) and `\/*` (until `*/`), as seen in the latter example above.]

I find this design — with or without comments — would naturally allow the programmer to choose between precision (singly quoted) and convenience/legibility (triply quoted). And of course it would allow breaking long string literals to multiple lines in a consistent way, which, for triply quoted strings, is also lighter than just concatenating with `+`.

— Pyry

PS. I also slightly regret that SE-0168 ended up stripping the trailing newline, because multiline strings seem to compose (concatenate) better with a trailing newline there by default. But I understand if the inconvenience of `print(str, terminator: "")` weighed more than the other option.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Two things:

Shall we rename the thread for to focus onto the new topic?

The toolchain is great, the multi-line string literal how I imagined it to be the whole time, except for two smaller issues.

The the fix-it is wrong for the following two examples:

"""
123<space>
"""

"""
abc
123<space>
"""
It will ask you to add \n\ for for the line behind the closing delimiter it only should be \. But a warning in such a case is the perfect direction for the whole debate we’re having in this thread.

The second issue is only out of my curiosity.

"""
Foo\<space><new_line_character>
"""
This results in an error right now. Is it possible to teach the compiler to swallow whitespace characters after the backslash until a new line character is found, simply said to ignore them, because in that case they are irrelevant and not harmful.

···

--
Adrian Zubarev
Sent with Airmail

Am 23. April 2017 um 13:30:34, John Holdsworth via swift-evolution (swift-evolution@swift.org) schrieb:

Following this thread it reads to me that SE-0168 being accepted without newline escapes was
regrettable as it gave us more flexibility in formatting “long strings”.

As the core team rejected it on the basis that it was inconsistent with conventional string literals the
obvious thing to do is raise a short micro-proposal that newline escape be introduced into both. This
would also bring them into line with C literals. I’ve drafted a new proposal we could discuss and which
I hope to submit tomorrow as the implementation is trivial if it’s not too late:

https://github.com/johnno1962c/swift-evolution/blob/master/proposals/0173-newline-escape-in-strings.md

For me personally, this would also have the happy side effect of making it possible to reopen the debate
about "should the final newline be stripped by default" as it could now so easily be escaped for those who
like their multiline literals missing a newline on the last line :)

I’ve updated the prototype toolchain to bring it into line with the Core team's decision available here:

http://johnholdsworth.com/swift-LOCAL-2017-04-22-a-osx.tar.gz

(This includes newline escaping on all strings but dutifully strips the last line)

As it looks like this patch might form the basis of the implementation in Swift 4, all testing appreciated.

https://github.com/apple/swift/pull/8813

-John

On 23 Apr 2017, at 10:41, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

Sure, I can give an example. I'm not going to suggest that it'd win any awards, but:

By restricting multiline literals to begin and end on distinct lines, the core team has established an interesting property. Namely, "literals" are delimited horizontally while """literals""" are delimited vertically.

To enable hard wrapping, permit continuation of literals by apposition of consecutive literals. That is, "Hello, " "world!" would be equivalent to "Hello, world!". This single rule can be applied to either kind of string literal. That is:

let a =
"Hello, "
"world!"

let b =
"""
Hello,
""" """
world!
"""

a == b // true

It certainly permits elided newlines. It is the exact same rule applied to both types of literals. It preserves code indentation and does not require single-line string literals to support code stripping. I leave it to your judgement whether it works "equally well" and/or is "horrible."
On Sun, Apr 23, 2017 at 04:13 Brent Royal-Gordon <brent@architechies.com> wrote:
On Apr 22, 2017, at 8:12 AM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Sat, Apr 22, 2017 at 3:38 AM, Brent Royal-Gordon <brent@architechies.com> wrote:
On Apr 21, 2017, at 11:48 AM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

This goes to my question to David Hart. Isn't this an argument for a feature to allow breaking a single-line string literal across multiple lines? What makes this a use case for some feature for _multiline_ string literals in particular?

Well, if you're breaking a string across several lines, you will want indentation stripping too. Are you suggesting we should also bring that feature to single-line string literals with escaped newlines?

No, I am suggesting that whatever design is used for escaped newlines, if at all possible it should be equally apt for "strings" and """strings""" such that it will not require indentation stripping.

Could you share an example of such a design? It doesn't have to be something you'd be happy to have in the language; it just needs to fit the following criteria:

* Permits non-significant hard-wrapping in a string literal.

* Works equally well with single and triple string literals.

* Preserves code indentation, but does not require single string literals to do indentation stripping.

* Is not horribly inconvenient.

--
Brent Royal-Gordon
Architechies

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Yep I really did pitched this instead of a triple quoted multi-line literal string.

let string =
    "Hello \ // Three trailing space characters
    "Swift\
    " 4.0" // Three leading space characters
      
print(string) // prints: "Hello___Swift___4.0" where _ is a space character
Ignore the comments above so we can focus on an easy design for both single and triple quoted literals.

The idea here was to fix the problem *continuation quotes* had and allow trailing precision. Now that we established a much simpler design for multi-line string literals, this can be reused in a much consistent way as a hard wrapping feature for both literals, where the backslash disables the new line injection in triple quoted literals.

···

--
Adrian Zubarev
Sent with Airmail

Am 23. April 2017 um 16:30:35, Adrian Zubarev (adrian.zubarev@devandartist.com) schrieb:

I’ve never thought about allowing hard wrapping from single quoted string literals until it come up during the latest discussion.

At first glance I don’t have anything against it. I wouldn’t put comments into the mix for now, to keep things simple. (I’ve already asked about comments, but the community rejected the idea _for now_.)

What was the exact use case for hard wrapping for the single quoted literals again? (Again I’m not against it.) Actually I believe I pitched a very similar design in the discussion thread (not during the review).

--
Adrian Zubarev
Sent with Airmail

Am 23. April 2017 um 13:14:35, Pyry Jahkola via swift-evolution (swift-evolution@swift.org) schrieb:

Hmm, I can see that Wux already replied to this question but let me give another more or less obvious answer which I believe has come up in a shape or another already:

Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org> wrote:

No, I am suggesting that whatever design is used for escaped newlines, if at all possible it should be equally apt for "strings" and """strings""" such that it will not require indentation stripping.

Could you share an example of such a design?

One way to achieve the criteria below for both singly and triply quoted strings would be to borrow the repeated opening quote syntax (from earlier discussions) for singly quoted strings:

let s1 = &quot;abc\\
          &quot;def\\n\\
          &quot;ghi \\
          &quot;xyz&quot;
assert\(s1 == &quot;abcdef\\nghi xyz&quot;\)

let s2 = &quot;abc\\
         &quot;def\\n\\
/\* Leading white space, \*/ &quot;ghi \\
// as well as comments

// and empty lines in between are
// insignificant when it comes to singly
// quoted literals\.
    &quot;xyz&quot;
assert\(s2 == s1\)

let s3 = &quot;&quot;&quot;
    abc\\
    def
    ghi \\
    xyz
    &quot;&quot;&quot;
assert\(s3 == s1\)

The criteria:

* Permits non-significant hard-wrapping in a string literal.

:white_check_mark: The string continues from the position of the backslash, with no extra space or line break inserted.

* Works equally well with single and triple string literals.

:white_check_mark: In both cases, a trailing `\` has the same meaning. In singly quoted strings, the only way to insert a newline is by quoting (`\n`), as it always was.

* Preserves code indentation, but does not require single string literals to do indentation stripping.

:white_check_mark: The indentation is just more explicit with singly quoted string literals.

* Is not horribly inconvenient.

:man_shrugging: Depends who you ask, I guess, but I think not horrible. And, after all, the programmer is free to choose between two quoting styles with different trade offs.

* * *

One thing that remains to be defined is whether trailing space is allowed (and ignored) after the backslash or not (and thus an error). I initially thought it's best to make into a compiler error, just like the indenting white space of the triple quoted string literals.

OTOH, we could also allow inline comments after the backslash:

let whyNot = &quot;this, \\
    &quot;that, \\ // &lt;\- Oxford comma
    &quot;and stuff&quot;
assert\(whyNot == &quot;this, that, and stuff&quot;\)

let list = &quot;&quot;&quot;
    \- this,
    \- that,\\n\\// comment using &quot;Adrian&#39;s \\n\\&quot;
    \- and stuff
    &quot;&quot;&quot;
assert\(list == &quot;\- this,\\n\- that,\\n\- and stuff&quot;\)

[Nit: If comments after the backslash were allowed, we'd need to either require a space after the backslash (e.g. `\ //`), or else accept as string continuation / comment start markers both `\//` (until newline) and `\/*` (until `*/`), as seen in the latter example above.]

I find this design — with or without comments — would naturally allow the programmer to choose between precision (singly quoted) and convenience/legibility (triply quoted). And of course it would allow breaking long string literals to multiple lines in a consistent way, which, for triply quoted strings, is also lighter than just concatenating with `+`.

— Pyry

PS. I also slightly regret that SE-0168 ended up stripping the trailing newline, because multiline strings seem to compose (concatenate) better with a trailing newline there by default. But I understand if the inconvenience of `print(str, terminator: "")` weighed more than the other option.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution