Optional dictionary subscripts

If you agree that these are all orthogonal pieces, then treat them as
such: I’d suggest that you provide a proposal that just tackles the
continuation string literals. This seems simple, and possible to get in
for Swift 3.

I've gone ahead and drafted this proposal, with some small extensions and
adjustments. See the "Draft Notes" section for details of what I've changed
and what concerns I have.

I don't feel like this proposal(draft) solves the issue we want(?) to solve with multi-line feature.

I expect to be able to have multiline text exactly *"as-is"* in my source file. No escaping, no interpolation, etc. I believe this should be a target of the proposal.
Otherwise, I reject to see any reason to introduce anything new at this area - we already can concatenate strings and place them on next line and escape special characters.

In your proposal, you have to escape characters in your text, you need to carefully modify the copy-pasted text to be allowed as correct multi-line string. Also, what if I need to have spaces *at the end of string* ? Editor can just trimmed them, and we can't clearly see them.

Personally I need to be able to have this(in some way) in my code:
(note this "\tuttorial" and "\(edition" - this is just text, I want to have inside my xml)

let xml = ... // some marker to start the multi-line str
<?xml version="1.0"?>
<catalog>
     <book id="myid" empty="">
         <author>myAuthor</author>
         <title>myTitle \tutorial 1\(edition 2)</title>
     </book>
</catalog>
... // some marker here to stop multi-line str

It seems like we need some markers for end-of-the-line to be able to keep spaces/tabs in the end of line.

What about something like this. Two suported variants : first when we need to keep spaces in the end of line, and second when we don't need spaced(will be trimmed by parser)

#1 (parser should just take the text between first and last quote *as-is*)

let xml = "\
"<?xml version="1.0"?> " // yes, *I need* these spaces at the end
"<catalog>"
" <book id="myid" empty="">"
" <author>myAuthor</author>"
" <title>myTitle \tutorial 1\(edition 2)</title>"
" </book>"
"</catalog>"
"

#2 in this case we don't need any spaces/tabs in the end of lines(don't care):
(parser takes all that is after | as-is but trims any trailing spaces/tabs in lines to be clear in behaviour)

let xml = "\

<?xml version="1.0"?>
<catalog>
   <book id="myid" empty="">
       <author>myAuthor</author>
       <title>myTitle \tutorial 1\(edition 2)</title>
   </book>
</catalog>

"

Or these two could be combined in one(as-is between |..|) but I'm not sure:

let xml = "\

<?xml version="1.0"?> | // yes, I need these spaces
<catalog>| // we have to have closing symbol in this case in other lines
   <book id="myid" empty="">|
       <author>myAuthor</author>|
       <title>myTitle \tutorial 1\(edition 2)</title>|
   </book>|
</catalog>|

"

···

On 27.04.2016 11:52, Brent Royal-Gordon via swift-evolution wrote:

Gist: <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f&gt;

  Multiline string literals

  * Proposal: SE-NNNN
    <https://github.com/apple/swift-evolution/blob/master/proposals/NNNN-name.md&gt;
  * Author(s): Brent Royal-Gordon <https://github.com/brentdax&gt;
  * Status: First Draft
  * Review manager: TBD

    <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#introduction&gt;Introduction

In Swift 2.2, the only means to insert a newline into a string literal is
the |\n| escape. String literals specified in this way are generally ugly
and unreadable. We propose a multiline string feature inspired by English
punctuation which is a straightforward extension of our existing string
literals.

Swift-evolution thread: multi-line string literals.
<https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160418/015500.html&gt;

    <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#draft-notes&gt;Draft
    Notes

  *

    This draft differs from the prototypes being thrown around on the list
    in that it specifies that comments should be treated as whitespace, and
    that whitespace-only lines in the middle of a multiline string should
    be ignored. I'm not sure if this is feasible from a parsing standpoint,
    and I'd like feedback from implementers on this point.

  *

    This draft also specifies diagnostics which should be included.
    Feedback on whether these are good choices would be welcome.

  *

    I am considering allowing you to put a backslash before the newline to
    indicate it should /not/ be included in the literal. In other words,
    this code:

    print("foo\
    "bar")

    Would print |"foobar"|. However, I think this should probably be
    proposed separately, because there may be a better way to do it.

  *

    I've listed only myself as an author because I don't want to put anyone
    else's name to a document they haven't seen, but there are others who
    deserve to be listed (John Holdsworth at least). Let me know if you
    think you should be included.

    <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#motivation&gt;Motivation

As Swift begins to move into roles beyond app development, code which needs
to generate text becomes a more important use case. Consider, for instance,
generating even a small XML string:

let xml = "<?xml version=\"1.0\"?>\n<catalog>\n\t<book id=\"bk101\"
empty=\"\">\n\t\t<author>\(author)</author>\n\t</book>\n</catalog>"

The string is practically unreadable, its structure drowned in escapes and
run-together characters; it looks like little more than line noise. We can
improve its readability somewhat by concatenating separate strings for each
line and using real tabs instead of |\t| escapes:

let xml = "<?xml version=\"1.0\"?>\n" +
          "<catalog>\n" +
          " <book id=\"bk101\" empty=\"\">\n" +
          " <author>\(author)</author>\n" +
          " </book>\n" +
          "</catalog>"

However, this creates a more complex expression for the type checker, and
there's still far more punctuation than ought to be necessary. If the most
important goal of Swift is making code readable, this kind of code falls
far short of that goal.

    <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#proposed-solution&gt;Proposed
    solution

We propose that, when Swift is parsing a string literal, if it reaches the
end of the line without encountering an end quote, it should look at the
next line. If it sees a quote mark there (a "continuation quote"), the
string literal contains a newline and then continues on that line.
Otherwise, the string literal is unterminated and syntactically invalid.

Our sample above could thus be written as:

let xml = "<?xml version=\"1.0\"?>
"<catalog>
          " <book id=\"bk101\" empty=\"\">
" <author>\(author)</author>
          " </book>
"</catalog>"

(Note that GitHub is applying incorrect syntax highlighting to this code
sample, because it's applying Swift 2 rules.)

This format's unbalanced quotes might strike some programmers as strange,
but it attempts to mimic the way multiple lines are quoted in English
prose. As an English Stack Exchange answer illustrates
<punctuation - Why does the multi-paragraph quotation rule exist? - English Language & Usage Stack Exchange

    “That seems like an odd way to use punctuation,” Tom said. “What harm
    would there be in using quotation marks at the end of every paragraph?”

    “Oh, that’s not all that complicated,” J.R. answered. “If you closed
    quotes at the end of every paragraph, then you would need to reidentify
    the speaker with every subsequent paragraph.

    “Say a narrative was describing two or three people engaged in a
    lengthy conversation. If you closed the quotation marks in the previous
    paragraph, then a reader wouldn’t be able to easily tell if the
    previous speaker was extending his point, or if someone else in the
    room had picked up the conversation. By leaving the previous
    paragraph’s quote unclosed, the reader knows that the previous speaker
    is still the one talking.”

    “Oh, that makes sense. Thanks!”

Similarly, omitting the ending quotation mark tells the code's reader (and
compiler) that the literal continues on the next line, while including the
continuation quote reminds the reader (and compiler) that this line is part
of a string literal.

      <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#benefits-of-continuation-quotes&gt;Benefits
      of continuation quotes

It would be simpler to not require continuation quotes, so why are they
required by this proposal? There are three reasons:

1.

    *They help the compiler pinpoint errors in string literal
    delimiting.* If continuation quotes were not required, then a missing
    end quote would be interpreted as a multiline string literal. This
    string literal would continue until the compiler encountered either
    another quote mark—perhaps at the site of another string literal or in
    a comment—or the end of the file. In either case, the compiler could at
    best only indicate the start of the runaway string literal; in
    pathological cases (for instance, if the next string literal
    was |"+"|), it might not even be able to do that properly.

    With continuation quotes required, if you forget to include an end
    quote, the compiler can tell that you did not intend to create a
    multiline string and flag the line that actually has the problem. It
    can also provide immediately actionable fix-it assistance. The fact
    that there is a redundant indication on each line of the programmer's
    intent to include that line in a multiline quote allows the compiler to
    guess the meaning of the code.

2.

    *They separate indentation from the string's contents.* Without
    continuation quotes, there would be no obvious indication of whether
    whitespace at the start of the line was intended to indent the string
    literal so it matched the surrounding code, or whether that whitespace
    was actually meant to be included in the resulting string. Multiline
    string literals would either have to put subsequent lines against the
    left margin, or apply error-prone heuristics to try to guess which
    whitespace was indentation and which was string literal content.

3.

    *They improve the ability to quickly recognize the literal.* The |"| on
    each line serves as an immediately obvious indication that the line is
    part of a string literal, not code, and the row of |"| characters in a
    well-formatted file allows you to quickly scan up and down the file to
    see the extent of the literal.

    <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#detailed-design&gt;Detailed
    design

When Swift is parsing a string literal and reaches the end of a line
without finding a closing quote, it examines the next line, applying the
following rules:

1.

    If the next line is all whitespace, it is ignored; Swift moves on to
    the line afterward, applying these rules again.

2.

    If the next line begins with whitespace followed by a continuation
    quote, then the string literal contains a newline followed by the
    contents of the string literal starting on that line. (This line may
    itself have no closing quote, in which case the same rules apply to the
    line which follows.)

3.

    If the next line contains anything else, Swift raises a syntax error
    for an unterminated string literal. This syntax error should offer two
    fix-its: one to close the string literal at the end of the current
    line, and one to include the next line in the string literal by
    inserting a continuation quote.

Rules 1 and 2 should treat comments as though they are whitespace; this
allows you to comment out individual lines in a multiline string literal.
(However, commenting out the last line of the string literal will still
make it unterminated, so you don't have a completely free hand in commenting.)

    <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#impact-on-existing-code&gt;Impact
    on existing code

Failing to close a string literal before the end of the line is currently a
syntax error, so no valid Swift code should be affected by this change.

    <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#alternatives-considered&gt;Alternatives
    considered

      <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#requiring-no-continuation-character&gt;Requiring
      no continuation character

The main alternative is to not require a continuation quote, and simply
extend the string literal from the starting quote to the ending quote,
including all newlines between them. For example:

let xml = "<?xml version=\"1.0\"?>
<catalog>
<book id=\"bk101\" empty=\"\">
<author>\(author)</author>
</book>
</catalog>"

This has several advantages:

1.

    It is simpler.

2.

    It is less offensive to programmers' sensibilities (since there are no
    unmatched |"| characters).

3.

    It does not require that you edit the string literal to insert a
    continuation quote in each line.

Balanced against the advantages, however, is the loss of the improved
diagnostics, code formatting, and visual affordances mentioned in the
"Benefits of continuation quotes" section above.

In practice, we believe that editor support (such as "Paste as String
Literal" or "Convert to String Literal" commands) can make adding
continuation quotes less burdensome, while also providing other
conveniences like automatic escaping. We believe the other two factors are
outweighed by the benefits of continuation quotes.

      <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#use-a-different-delimiter-for-multiline-strings&gt;Use
      a different delimiter for multiline strings

The initial suggestion was that multiline strings should use a different
delimiter, |"""|, at the beginning and end of the string, with no
continuation characters between. This solution was rejected because it has
the same issues as the "no continuation character" solution, and because it
was mixing two orthogonal issues (multiline strings and alternate delimiters).

Another suggestion was to support a heredoc syntax, which would allow you
to specify a placeholder string literal on one line whose content begins on
the next line, running until some arbitrary delimiter. For instance, if
Swift adopted Perl 5's syntax, it might support code like:

connection.sendString(<<"END")
<?xml version="1.0"?>
<catalog>
    <book id="bk101" empty="">
        <author>\(author)</author>
    </book>
</catalog>
END

In addition to the issues with the |"""| syntax, heredocs are complicated
both to explain and to parse, and are not a natural extension of Swift's
current string syntax.

Both of these suggestions address interesting issues with string literals,
solving compelling use cases. They're just not that good at fixing the
specific issue at hand. We might consider them in the future to address
those problems to which they are better suited.

      <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#fixing-other-string-literal-readability-issues&gt;Fixing
      other string literal readability issues

This proposal is narrowly aimed at multiline strings. It intentionally
doesn't tackle several other problems with string literals:

  *

    Reducing the amount of double-backslashing needed when working with
    regular expression libraries, Windows paths, source code generation,
    and other tasks where backslashes are part of the data.

  *

    Alternate delimiters or other strategies for writing strings
    with |"| characters in them.

  *

    String literals consisting of very long pieces of text which are best
    represented completely verbatim.

These are likely to be subjects of future proposals, though not necessarily
during Swift 3.

This proposal also does not attempt to address regular expression literals.
The members of the core team who are interested in regular expression
support have ambitions for that feature which put it out of scope for Swift 3.

--
Brent Royal-Gordon
Architechies

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

Regards
(From mobile)

If you agree that these are all orthogonal pieces, then treat them as such: I’d suggest that you provide a proposal that just tackles the continuation string literals. This seems simple, and possible to get in for Swift 3.

I've gone ahead and drafted this proposal, with some small extensions and adjustments. See the "Draft Notes" section for details of what I've changed and what concerns I have.

Gist: <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f&gt;

Multiline string literals
Proposal: SE-NNNN
Author(s): Brent Royal-Gordon
Status: First Draft
Review manager: TBD
Introduction

In Swift 2.2, the only means to insert a newline into a string literal is the \n escape. String literals specified in this way are generally ugly and unreadable. We propose a multiline string feature inspired by English punctuation which is a straightforward extension of our existing string literals.

Swift-evolution thread: multi-line string literals.

Draft Notes

This draft differs from the prototypes being thrown around on the list in that it specifies that comments should be treated as whitespace, and that whitespace-only lines in the middle of a multiline string should be ignored. I'm not sure if this is feasible from a parsing standpoint, and I'd like feedback from implementers on this point.

This draft also specifies diagnostics which should be included. Feedback on whether these are good choices would be welcome.

I am considering allowing you to put a backslash before the newline to indicate it should not be included in the literal. In other words, this code:

print("foo\
"bar")
Would print "foobar". However, I think this should probably be proposed separately, because there may be a better way to do it.

I've listed only myself as an author because I don't want to put anyone else's name to a document they haven't seen, but there are others who deserve to be listed (John Holdsworth at least). Let me know if you think you should be included.

Motivation

As Swift begins to move into roles beyond app development, code which needs to generate text becomes a more important use case. Consider, for instance, generating even a small XML string:

let xml = "<?xml version=\"1.0\"?>\n<catalog>\n\t<book id=\"bk101\" empty=\"\">\n\t\t<author>\(author)</author>\n\t</book>\n</catalog>"
The string is practically unreadable, its structure drowned in escapes and run-together characters; it looks like little more than line noise. We can improve its readability somewhat by concatenating separate strings for each line and using real tabs instead of \t escapes:

let xml = "<?xml version=\"1.0\"?>\n" +
          "<catalog>\n" +
          " <book id=\"bk101\" empty=\"\">\n" +
          " <author>\(author)</author>\n" +
          " </book>\n" +
          "</catalog>"
However, this creates a more complex expression for the type checker, and there's still far more punctuation than ought to be necessary. If the most important goal of Swift is making code readable, this kind of code falls far short of that goal.

Proposed solution

We propose that, when Swift is parsing a string literal, if it reaches the end of the line without encountering an end quote, it should look at the next line. If it sees a quote mark there (a "continuation quote"), the string literal contains a newline and then continues on that line. Otherwise, the string literal is unterminated and syntactically invalid.

Our sample above could thus be written as:

let xml = "<?xml version=\"1.0\"?>
          "<catalog>
          " <book id=\"bk101\" empty=\"\">
          " <author>\(author)</author>
          " </book>
          "</catalog>"

Somehow I find the fundamental asymetry of this syntax disturbing for the eye (many years of programming have created this silent but real expectation that " should match). The thought that it might be trying to mimic "english prose" does not make it suddenly look pretty or likeable. But again I probably have no taste as I used to find heredoc in perl/shell, if not pretty, at least practical.
I think what I find surprising is what I perceive as a what-we-give-with-the-left-hand (the promise of a convenient way to insert existing external text), we-take-back-with-the-right: yes you can insert text, but you will have to massage it so much that you are going to be detered from using it for anything past 10 lines.

(Note that GitHub is applying incorrect syntax highlighting to this code sample, because it's applying Swift 2 rules.)

This format's unbalanced quotes might strike some programmers as strange, but it attempts to mimic the way multiple lines are quoted in English prose. As an English Stack Exchange answer illustrates:

“That seems like an odd way to use punctuation,” Tom said. “What harm would there be in using quotation marks at the end of every paragraph?”

“Oh, that’s not all that complicated,” J.R. answered. “If you closed quotes at the end of every paragraph, then you would need to reidentify the speaker with every subsequent paragraph.

“Say a narrative was describing two or three people engaged in a lengthy conversation. If you closed the quotation marks in the previous paragraph, then a reader wouldn’t be able to easily tell if the previous speaker was extending his point, or if someone else in the room had picked up the conversation. By leaving the previous paragraph’s quote unclosed, the reader knows that the previous speaker is still the one talking.”

“Oh, that makes sense. Thanks!”
Similarly, omitting the ending quotation mark tells the code's reader (and compiler) that the literal continues on the next line, while including the continuation quote reminds the reader (and compiler) that this line is part of a string literal.

I certainly lack imagination as a missing quote does not make my mind immediately scream 'of course, it will be on the next line, or the one after, or maybe later... keep looking for it'.

···

On Apr 27, 2016, at 10:52 AM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org> wrote:

Benefits of continuation quotes

It would be simpler to not require continuation quotes, so why are they required by this proposal? There are three reasons:

They help the compiler pinpoint errors in string literal delimiting. If continuation quotes were not required, then a missing end quote would be interpreted as a multiline string literal. This string literal would continue until the compiler encountered either another quote mark—perhaps at the site of another string literal or in a comment—or the end of the file. In either case, the compiler could at best only indicate the start of the runaway string literal; in pathological cases (for instance, if the next string literal was "+"), it might not even be able to do that properly.

With continuation quotes required, if you forget to include an end quote, the compiler can tell that you did not intend to create a multiline string and flag the line that actually has the problem. It can also provide immediately actionable fix-it assistance. The fact that there is a redundant indication on each line of the programmer's intent to include that line in a multiline quote allows the compiler to guess the meaning of the code.

They separate indentation from the string's contents. Without continuation quotes, there would be no obvious indication of whether whitespace at the start of the line was intended to indent the string literal so it matched the surrounding code, or whether that whitespace was actually meant to be included in the resulting string. Multiline string literals would either have to put subsequent lines against the left margin, or apply error-prone heuristics to try to guess which whitespace was indentation and which was string literal content.

They improve the ability to quickly recognize the literal. The " on each line serves as an immediately obvious indication that the line is part of a string literal, not code, and the row of " characters in a well-formatted file allows you to quickly scan up and down the file to see the extent of the literal.

Detailed design

When Swift is parsing a string literal and reaches the end of a line without finding a closing quote, it examines the next line, applying the following rules:

If the next line is all whitespace, it is ignored; Swift moves on to the line afterward, applying these rules again.

If the next line begins with whitespace followed by a continuation quote, then the string literal contains a newline followed by the contents of the string literal starting on that line. (This line may itself have no closing quote, in which case the same rules apply to the line which follows.)

If the next line contains anything else, Swift raises a syntax error for an unterminated string literal. This syntax error should offer two fix-its: one to close the string literal at the end of the current line, and one to include the next line in the string literal by inserting a continuation quote.

Rules 1 and 2 should treat comments as though they are whitespace; this allows you to comment out individual lines in a multiline string literal. (However, commenting out the last line of the string literal will still make it unterminated, so you don't have a completely free hand in commenting.)

Impact on existing code

Failing to close a string literal before the end of the line is currently a syntax error, so no valid Swift code should be affected by this change.

Alternatives considered

Requiring no continuation character

The main alternative is to not require a continuation quote, and simply extend the string literal from the starting quote to the ending quote, including all newlines between them. For example:

let xml = "<?xml version=\"1.0\"?>
<catalog>
    <book id=\"bk101\" empty=\"\">
        <author>\(author)</author>
    </book>
</catalog>"
This has several advantages:

It is simpler.

It is less offensive to programmers' sensibilities (since there are no unmatched " characters).

It does not require that you edit the string literal to insert a continuation quote in each line.

Balanced against the advantages, however, is the loss of the improved diagnostics, code formatting, and visual affordances mentioned in the "Benefits of continuation quotes" section above.

In practice, we believe that editor support (such as "Paste as String Literal" or "Convert to String Literal" commands) can make adding continuation quotes less burdensome, while also providing other conveniences like automatic escaping. We believe the other two factors are outweighed by the benefits of continuation quotes.

Use a different delimiter for multiline strings

The initial suggestion was that multiline strings should use a different delimiter, """, at the beginning and end of the string, with no continuation characters between. This solution was rejected because it has the same issues as the "no continuation character" solution, and because it was mixing two orthogonal issues (multiline strings and alternate delimiters).

Another suggestion was to support a heredoc syntax, which would allow you to specify a placeholder string literal on one line whose content begins on the next line, running until some arbitrary delimiter. For instance, if Swift adopted Perl 5's syntax, it might support code like:

connection.sendString(<<"END")
<?xml version="1.0"?>
<catalog>
    <book id="bk101" empty="">
        <author>\(author)</author>
    </book>
</catalog>
END
In addition to the issues with the """ syntax, heredocs are complicated both to explain and to parse, and are not a natural extension of Swift's current string syntax.

Both of these suggestions address interesting issues with string literals, solving compelling use cases. They're just not that good at fixing the specific issue at hand. We might consider them in the future to address those problems to which they are better suited.

Fixing other string literal readability issues

This proposal is narrowly aimed at multiline strings. It intentionally doesn't tackle several other problems with string literals:

Reducing the amount of double-backslashing needed when working with regular expression libraries, Windows paths, source code generation, and other tasks where backslashes are part of the data.

Alternate delimiters or other strategies for writing strings with " characters in them.

String literals consisting of very long pieces of text which are best represented completely verbatim.

These are likely to be subjects of future proposals, though not necessarily during Swift 3.

This proposal also does not attempt to address regular expression literals. The members of the core team who are interested in regular expression support have ambitions for that feature which put it out of scope for Swift 3.

--
Brent Royal-Gordon
Architechies

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

Same here. IMHO, there needs to be a version of multi line strings that's doesn't require to prefix a token on each line.

···

On 30 Apr 2016, at 09:20, Daniel Phillips via swift-evolution <swift-evolution@swift.org> wrote:

Sorry for any extra noise here. I've read the 58 emails in this thread and I just wanted to chime in my support for Dave here.

I think a multiline string literal implementation along the lines of Python is a no brainer.

In particular when I've needed and wanted multiline string literals it has almost always been when I've wanted to embed text from somewhere external (a text file for example, or string contents of a JSON file as part of unit testing).

Needing to append a token at the beginning of each line of my text would make multiline string literals considerably less productive for myself.

Just thought I'd chime in with that. Sorry again for the extra noise.

Regards,
Daniel

On 26 Apr 2016, at 10:55 pm, Dave Abrahams via swift-evolution <swift-evolution@swift.org> wrote:

on Sun Apr 24 2016, John Holdsworth <swift-evolution@swift.org> wrote:

To audition Xcode using the following multi-line syntax:

let xml = "<?xml version=\"1.0\"?>
"<catalog>
" <book id=\"bk101\" empty=\"\">
" <author>\(author)</author>
" <title>XML Developer's Guide</title>
" <genre>Computer</genre>
" <price>44.95</price>
" <publish_date>2000-10-01</publish_date>
" <description>An in-depth look at creating applications with XML.</description>
" </book>
"</catalog>
""
print(xml)

You can install:
http://johnholdsworth.com/swift-LOCAL-2016-04-25-a-osx.tar.gz

Personally, I don't like that this syntax requires the moral equivalent
of a continuation character. It means I need to run a regex
search/replace over my text after I paste it between quotation marks.

  On 24 Apr 2016, at 23:35, Chris Lattner <clattner@apple.com> wrote:

      On Apr 23, 2016, at 2:08 PM, Brent Royal-Gordon via swift-evolution >>> <swift-evolution@swift.org> wrote:

      I’m trying to avoid more advanced features such as the handling of
          indenting which
          for me complicates something that if kept simple can be documented
          very easily.

      I don't think you can tackle multiline strings without worrying about
      indenting. Indentation may fundamentally change the approach you choose.

  I agree with this and almost every point you make in your email (and your
  other subsequent one about one approach maximally general). That said, I
  wonder if there is a different conclusion that can be reached. I’m going to
  rearrange your three features a bit:

      The way I would prefer to tackle these is:

      * Multiline literals: If the closing quote of a string is not present,
      look at the next line. If it consists of (optional) indentation followed
      by a matching opening quote, the string has a newline and then continues
      after the quote on the next line. (The handling of comments is an open
      question here.)

      let xml: String = "<?xml version=\"1.0\"?>
      "<catalog>
      "\t<book id=\"bk101\" empty=\"\">
      "\t\t<author>\(author)</author>
      "\t</book>
      "</catalog>"

      The cool things about this are that (a) the compiler can tell you really
      do mean this to be part of the literal and you haven't just forgotten to
      close the string, and (b) there's no guesswork about how indentation
      should be handled. The uncool thing is that you need to insert the quote
      at the beginning of each line, so you can't just blindly paste into a
      multiline literal. Editors can help make that easier, though—a "paste as
      string literal" feature would be a nice addition to Xcode, and not just
      for multiline strings or just for Swift.

  Yes, I completely agree. This is is awesome, and a nice & simple
  generalization of our existing syntax. It has obvious behavior even if you
  encounter it in code without knowing about the feature.

      * Disabling escapes: If you use single quotes instead of double quotes,
      backslash escapes are disabled.

  We need a way to disable escapes, but it seems to me that (since it is
  orthogonal to the other concerns) that it should not be tied to the
  “multiple single quotes” syntax. What is your thought on “modifier” prefix
  characters for string literals? e.g.:

  let x = e”no \escapes \(processed here”

  If we supported these, they would be supported with multi-line string
  literals by putting the modifiers on the first line of the literal, and the
  multi-line approach above would “just work”. You could introduce several
  different modifiers, e.g. one that disabled general escapes, but still
  allowed \(x) for substitution.

      * Yes, with a number of backslashes matching the number of quotes, which
      allows you to insert literal \( text: ''' <author>\\\(author)</author>

  Egads!

      Notes on alternatives:

      1. If you wanted to not provide no-escaping strings, an alternative
      would be to say that *all* escapes require as many backslashes as there
      are quotes in the string delimiter. Thus, a newline escape in a `"""`
      string would be `\\\n`. This would in practice give you the same
      flexibility to write a literal without worrying (much) about escaping.

  I’m really not a fan of requiring “stacking” of escapes to re-enable them.
  This (IMO) just makes it less likely that you’ll run into an edge case. I
  also don’t like the “fix" being to have to use 5 quotes around your strings :
  -)

      3. It might be useful to make multiline `"` strings trim trailing
      whitespace and comments like Perl's `/x` regex modifier does.

  If you have modifier characters already, it is easy to build a small zoo
  full of these useful beasts.

      * Alternative delimiters: If a string literal starts with three, or
      five, or seven, or etc. quotes, that is the delimiter, and fewer quotes
      than that in a row are simply literal quote marks. Four, six, etc.
      quotes is a quote mark abutting the end of the literal.

      let xml: String = """<?xml version="1.0"?>
      """<catalog>
      """\t<book id="bk101" empty="">
      """\t\t<author>\(author)</author>
      """\t</book>
      """</catalog>"""

      You can't use this syntax to express an empty string, or a string
      consisting entirely of quote marks, but `""` handles empty strings
      adequately, and escaping can help with quote marks. (An alternative
      would be to remove the abutting rule and permit `""""""` to mean "empty
      string", but abutting quotes seem more useful than long-delimiter empty
      strings.)

  I agree that there is a need to support alternative delimiters, but
  subjectively, I find this to be pretty ugly. It is also a really unfortunate
  degenerate case for “I just want a large blob of XML” because you’d end up
  using “"” almost all the time, and you have to use it on every line.

  For cases like this, I think it would be reasonable to have a “heredoc” like
  scheme, which does not allow leading indentation, and does work with all the
  same modifier characters above. I do not have a preference on a particular
  syntax, and haven’t given it any thought, but this would allow you to do
  things like:

  let str = <<EOF
  <?xml version="1.0"?>
  <catalog>
  \t<book id="bk101" empty="">
  \t\t<author>\(author)</author>
  \t</book>
  </catalog>
  EOF

  for example. You could then turn off escaping and other knobs using the
  modifier character (somehow, it would have to be incorporated into the
  syntax of course).

  I generally agree with your down thread remarks about how Swift doesn’t like
  to have multiple different solutions for the same problem. OTOH, you could
  look at “” syntax as being analogous to closure exprs, and heredoc syntax as
  being analogous to nested functions :-)

  -Chris

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

--
Dave

_______________________________________________
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

Thanks Brent for pulling together the proposal and summarising this thread.

I have to say I still feel most drawn to your “continuation quotes” idea and after
some thought the “_” modifier for _”strings”with”quotes”_ also seems sensible.
Most of all, for me the appeal of these approaches is their absolute simplicity.
My only reservation is what external editors will make of these strings as there
is no precedent in another programming language I am aware of.

I’ve updated the "reference toolchain" and PR for testing and review.

http://johnholdsworth.com/swift-LOCAL-2016-05-01-a-osx.tar.gz

This implementation still contains the “e” modifier as an example of how they
would be lexed (which I’ll remove before submission as it is outside the scope
of this proposal) and one new feature that \ before a newline ignores the newline.
In this implementation modifiers can only be applied to the first segment of the literal.

This makes the following strings valid to my mind:

        let xml = "\
            "<?xml version=\"1.0\"?>
            "<catalog>
            " <book id=\"bk101\" empty=\"\">
            " <author>\(author)</author>
            " <title>XML Developer's Guide</title>
            " <genre>Computer</genre>
            " <price>44.95</price>
            " <publish_date>2000-10-01</publish_date>
            " <description>An in-depth look at creating \
                        "applications with XML.</description>
            " </book>
            "</catalog>
            ""
        print(xml)

        assert( xml == _"<?xml version="1.0"?>
            "<catalog>
            " <book id="bk101" empty="">
            " <author>\(author)</author>
            " <title>XML Developer's Guide</title>
            " <genre>Computer</genre>
            " <price>44.95</price>
            " <publish_date>2000-10-01</publish_date>
            " <description>An in-depth look at creating applications with XML.</description>
            " </book>
            "</catalog>
            ""_ )

        try! NSRegularExpression(pattern: e"<([a-zA-Z][\w]*)", options: )
            .enumerateMatches(in: xml, options: , range: NSMakeRange(0, xml.utf16.count)) {
                (result, flags, stop) in
                print((xml as NSString).substring( with:result!.range(at: 1)))
        }

I’d not create a lexStringMultilineLiteral() function just yet as the changes are still minor as you
can see from the PR and due to the fact you can’t determine if a string is multiline until you
are half way through it. Excuse the “bottom up" approach but the reasoning is it would be no
accident that if the lexer and any changes to it are minimal, it will be easy to document and use.

John

···

On 1 May 2016, at 13:04, L Mihalkovic <laurent.mihalkovic@gmail.com> wrote:

[couple minutes read]

I read with great attention this thread, trying to see it from the implementation viewpoint (I know that the compiler structure should not drive the language features). I also revisited the how-to-contribute notes as well as the dev-process description. One of the ideas that stood out in my mind was that when looking at an implementation, enablement changes should be separated from the bulk of the feature, such that reviews can be easier.

So I tried to elevate this to the rank of a hidden-mandatory-requirement for anything related to this feature. It lead me to a staged approach to this feature that would allow a lot of things to be done, OVER TIME.

When distilling this feature to the smallest part enabler that would have to be added to the compiler I came to the following short list

add a string_multiline_token to the lexer
I realize that the current lexer can be tweaked to work (as per John’s PR), but IMO adding a dedicated "hole" in the parsing code is what will give something working today (no difference with current compiler behavior) while allowing all future changes to be cleanly isolated from anything around
if one accepts the idea of a hole created by the token, then it stands to reason to have delimiters around it. I looking at the structure of the grammar, I came to the conclusion that _” and “_ where an easy, unambiguous choice (I believe “”” and “”” looked like an equally easy an unambiguous choice)
the next choice should be the creation of a lexStringMultilineLiteral() and lexMultilineCharacter() method in the Lexer. Again… bare with me, I do believe it is relevant to what everyone wants this feature to be… The latter method should contain only extensions specific to multiline literals delegating common use cases to lexCharacter()

The main point of following this route (or any equivalent) is that
it represents a very clear commitment to multiline string literals
it ensures that there is no strong commitment to feature details, while allowing many future scenarios
it will remain backward compatible with enhancements to the current string literal syntax (translation?)
external contributors will be able to prototype while making sure we stay within strict boundaries for integration with the compiler

The next equally small step would be to describe the required minimal changes to Parser, a step I do not want to take now if the compiler experts view no merit at all to the proposed staged approach.

A thought experiment pushing further down this path, shows how the following would be equally possible language features (with roughly equivalent implementation cost):

let whyOwhy = “”"\
    !! Can't understand what improvements it truly delivers
    !! It basically removes a handful of characters
    !! It works today
    !! But I don't see it as a likable foundations for adding in future enhancements
    !!\
    !! I don't envy the people who will have to support it outside of xcode
    !! Or even in xcode (considering how it currently struggles with indents/formatting
    !! As for elegance, beauty is in the eye of the beholder, they say.
“”"
var json1 = _"[json]\
    !!{
    !! "file" : "\(wishIhadPlaceholders)_000.md"
    !! "desc" : "and why are all examples in xml, i thought it died a while ago ;-)"
    !! "rational" : [
    !! "Here we go again"
    !! "How will xcode help make these workable"
    !! ]
    !!}
“_
var json2 = _"[json]\
{
  "file" : "\(wishIhadPlaceholders)_000.md"
  "desc" : "and why are all examples in xml, i thought it died a while ago ;-)"
  "rational" : [
          "Here we go again"
          "How will xcode help make these workable"
       ]
}
“_

[_"] --> start string
[_"\] --> start line + ignore spaces until eol (basically swallow \r\n)
[!!\] --> ignore everything until eol... basically the gap does not exits
["_] --> terminate string
[_"[TYPEID]\] --> start string knowing that it a verifyer or a formatter (or a chain of) understanding TYPEID can syntax check or format or or or

IMO splitting these expression from the current lexing/parsing has another long term benefits when coupled with the aforementioned idea of contents tagging:
allow external dedicated formatter to be created in any editor supporting swift
allow external validators (including in the form of compiler plugins)
open a door for an equivalent to the scala's macros for contents marked as [swift]

Once again I fully appreciate that implementation should not drive language design, but considering the flurry of great ideas, I thought it might in this instance be useful to identify a minimal, noncommittal, direction common to many scenarios, such that a step can be taken that will neither favor nor prohibit any of the proposals, but simply enable them all.

Thank you for your patience
Regards

PS: I am working on a rudimentary implementation that I hope could help people test all the ideas floating in this list.

On Apr 26, 2016, at 8:04 AM, Chris Lattner via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Apr 25, 2016, at 5:22 PM, Brent Royal-Gordon <brent@architechies.com <mailto:brent@architechies.com>> wrote:

3. It might be useful to make multiline `"` strings trim trailing whitespace and comments like Perl's `/x` regex modifier does.

If you have modifier characters already, it is easy to build a small zoo full of these useful beasts.

Modifiers are definitely a workable alternative, and can be quite flexible, particularly if a future macro system can let you create new modifiers.

Right. I consider modifiers to be highly precedented in other languages, and therefore proven to work. If we go this way, I greatly prefer prefix to postfix modifiers.

* Alternative delimiters: If a string literal starts with three, or five, or seven, or etc. quotes, that is the delimiter, and fewer quotes than that in a row are simply literal quote marks. Four, six, etc. quotes is a quote mark abutting the end of the literal.

  let xml: String = """<?xml version="1.0"?>
        """<catalog>
        """\t<book id="bk101" empty="">
        """\t\t<author>\(author)</author>
        """\t</book>
        """</catalog>"""

You can't use this syntax to express an empty string, or a string consisting entirely of quote marks, but `""` handles empty strings adequately, and escaping can help with quote marks. (An alternative would be to remove the abutting rule and permit `""""""` to mean "empty string", but abutting quotes seem more useful than long-delimiter empty strings.)

I agree that there is a need to support alternative delimiters, but subjectively, I find this to be pretty ugly. It is also a really unfortunate degenerate case for “I just want a large blob of XML” because you’d end up using “"” almost all the time, and you have to use it on every line.

On the other hand, the `"""` does form a much larger, more obvious continuation indicator. It is *extremely* obvious that the above line is not Swift code, but something else embedded in it. It's also extremely obvious what its extent is: when you stop seeing `"""`, you're back to normal Swift code.

Right, but it is also heavy weight and ugly. In your previous email you said about the single quote approach: "The quotation marks on the left end up forming a column that marks the lines as special”, so I don’t see a need for a triple quote syntax to solve this specific problem.

I *really* don't like the idea of our only alternatives being "one double-quote mark with backslashing" or "use an entire heredoc". Heredocs have their place, but they are a *very* heavyweight quoting mechanism, and relatively short strings with many double-quotes are pretty common. (Consider, for instance, strings containing unparsed JSON.) I think we need *some* alternative to double-quotes, either single-quotes (with the same semantics, just as an alternative) or this kind of quote-stacking.

I agree that this is a real problem that would be great to solve.

If I step back and look at the string literal space we’re discussing, I feel like there are three options:

1) single and simple multiline strings, using “
2) your triple quote sort of string, specifically tuned to avoid having to escape “ when it occurs once or twice in sequence.
3) heredoc, which is a very general (but also very heavy weight) solution to quoting problems.

I’m trying to eliminate the middle one, so we only have to have "two things”. Here are some alternative ways to solve the problem, which might have less of an impact on the language:

A) Introduce single quoted string literals to avoid double quote problems specifically, e.g.: ‘look “here” I say!’. This is another form of #2 which is less ugly. It also doesn’t help you if you have both “ and ‘ in your string.

B) Introduce a modifier character that requires a more complex closing sequence to close off the string, see C++ raw string literals for prior art on this approach. Perhaps something like:

   Rxxx”look “ here “ I can use quotes “xxx

That said, I still prefer C) "ignore this issue for now”. In other words, I wouldn’t want to block progress on improving the string literal situation overall on this issue, because anything we do here is an further extension to a proposal that doesn’t solve this problem.

For cases like this, I think it would be reasonable to have a “heredoc” like scheme, which does not allow leading indentation, and does work with all the same modifier characters above. I do not have a preference on a particular syntax, and haven’t given it any thought, but this would allow you to do things like:

  let str = <<EOF
<?xml version="1.0"?>
<catalog>
\t<book id="bk101" empty="">
\t\t<author>\(author)</author>
\t</book>
</catalog>
EOF

for example. You could then turn off escaping and other knobs using the modifier character (somehow, it would have to be incorporated into the syntax of course).

There are two questions and a suggestion I have whenever heredoc syntax comes up.

Q1: Does the heredoc begin immediately, at the next line, or at the next valid place for a statement to start? Heredocs traditionally take the second approach.

Q2: Do you permit heredocs to stack—that is, for a single line to specify multiple heredocs?

S: During the Perl 6 redesign, they decided to use the delimiter's indentation to determine the base indentation for the heredoc:

  func x() -> String {
    return <<EOF
    <?xml version="1.0"?>
    <catalog>
    \t<book id="bk101" empty="">
    \t\t<author>\(author)</author>
    \t</book>
    </catalog>
    EOF
  }

Does that seem like a good approach?

I think that either approach could work, that you have a lot more experience on these topics than I do, and I would expect a vigorous community debate about these topics. :-)

That said, if you look at what we’re discussing:

1. “Continuation" string literals, to allow a multi-line string literal. You and I appear to completely agree about this.
2. Heredoc: You and I seem to agree that they are a good “fully general” solution to have, but there are the details you outline above to iron out.
3. Modifier characters: I’m in favor, but I don’t know where you stand. There is also still much to iron out here (such as the specific characters).
4. A way to avoid having to escape “ in a non-heredoc literal. I’m still unconvinced, and think that any solution to this problem will be orthogonal to the problems solved by 1-3 (and therefore can be added after getting experience with the other parts).

If you agree that these are all orthogonal pieces, then treat them as such: I’d suggest that you provide a proposal that just tackles the continuation string literals. This seems simple, and possible to get in for Swift 3. After that, we can discuss heredoc and modifiers (if you think they’re a good solution) on their own threads. If those turn out to be uncontroversial, then perhaps they can get in too.

On the heredoc aspects specifically, unless others chime in with strong opinions about the topics you brought up, I’d suggest that you craft a proposal for adding them with your preferred solution to these. You can mention the other answers (along with their tradeoffs and rationale for why you picked whatever you think is right) in the proposal, and we can help the community hash it out.

What do you think?

-Chris

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

In my opinion, one problem is that we don’t have a reference to a
laundry or wish list of what features we would like around string
literals in the language. Without evaluating a proposal against all of
those features (moves forward, doesn’t impact, creates later issues
for) it is hard to evaluate.

+1, thank you!

···

on Sat Apr 30 2016, David Waite <swift-evolution@swift.org> wrote:

My guess here at an exhaustive list:

Main goals:
- reduce the impact on readability when dealing with certain kinds of string literals
- reduce the amount of editing needed when inserting/referencing text from an external source to be used as a string literal

Specific tasks/asks:
- for large string literals, reduce the amount of editing needed to span multiple lines
- for strings literals meant to represent multi-line text, allow the visual newline to be used rather than an encoding
  (note: this may mean in the first case newlines are considered
formatting of the literal, while in the second they are considered
part of the represented text)
- with string literals spanning multiple lines, allow for the author
to indent the literal to match flow with surrounding code without
impacting the represented text
- allow for text with double quotes to be represented in a string literal without requiring those quotes to be escaped
- have the ability to disable all/most escape interpretation to reduce impact on readability of certain text
- take into account that regular expressions, when added, will likely
require different escaping rules than text string literals

Approach-specific
- if allowing for inline blocks of strings delimited by start/end points e.g. here docs, data segments
  - if the block end is on its own line, control whether that newline is part of the represented text

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

--
Dave

I expect to be able to have multiline text exactly *"as-is"* in my source file. No escaping, no interpolation, etc. I believe this should be a target of the proposal.

I think that's a great feature we should also add. I just think it's a *different* feature from this one. That's why I listed it in the "Fixing other string literal readability issues" part of the "Alternatives considered" section as something I think is worth fixing.

Otherwise, I reject to see any reason to introduce anything new at this area - we already can concatenate strings and place them on next line and escape special characters.

Sure, but it's a lot less easy to understand what's going on. See the examples in the "Motivation" and "Proposed solution" sections.

Also, what if I need to have spaces *at the end of string* ? Editor can just trimmed them, and we can't clearly see them.

One way to address this is with a "zero-width escape", an escape which doesn't actually insert anything but merely breaks up sequences and protects whitespace in front of it.

Of course, using tools which don't modify whitespace in string literals since doing so affects the program's behavior is probably the "correct" answer here...

···

--
Brent Royal-Gordon
Architechies

FWIW, this syntax may also be difficult for various editors, IDEs,
scripts, and pretty-printers to adjust to. One benefit of Python's
triple-quoted syntax is that applying the usual rules for string
recognition results in getting the boundaries of a multi-line string
correct to within a couple of characters, and syntax highlighting always
works.

···

on Wed Apr 27 2016, "L. Mihalkovic via swift-evolution" <swift-evolution@swift.org> wrote:

Somehow I find the fundamental asymetry of this syntax disturbing for the eye
(many years of programming have created this silent but real expectation that "
should match). The thought that it might be trying to mimic "english prose" does
not make it suddenly look pretty or likeable. But again I probably have no taste
as I used to find heredoc in perl/shell, if not pretty, at least practical.
I think what I find surprising is what I perceive as a
what-we-give-with-the-left-hand (the promise of a convenient way to insert
existing external text), we-take-back-with-the-right: yes you can insert text,
but you will have to massage it so much that you are going to be detered from
using it for anything past 10 lines.

--
Dave

I expect to be able to have multiline text exactly *"as-is"* in my source
file. No escaping, no interpolation, etc. I believe this should be a target
of the proposal.

I also see this as one of the most important goals of any multi-line
string-handling proposal. The "no escapes required" syntax doesn't have to
be the only way to handle multi-line strings, but it should be one of the
available ways.

-John

P.S. - Secondarily (and broader than just multi-line strings) I think there
should also be a way to avoid backslash-itis in strings of all kinds by
providing some flexibility in string delimiters. But that's for another
thread…

···

On Wed, Apr 27, 2016 at 9:08 AM, Vladimir.S via swift-evolution < swift-evolution@swift.org> wrote:

Otherwise, I reject to see any reason to introduce anything new at this
area - we already can concatenate strings and place them on next line and
escape special characters.

In your proposal, you have to escape characters in your text, you need to
carefully modify the copy-pasted text to be allowed as correct multi-line
string. Also, what if I need to have spaces *at the end of string* ? Editor
can just trimmed them, and we can't clearly see them.

Personally I need to be able to have this(in some way) in my code:
(note this "\tuttorial" and "\(edition" - this is just text, I want to
have inside my xml)

let xml = ... // some marker to start the multi-line str
<?xml version="1.0"?>
<catalog>
    <book id="myid" empty="">
        <author>myAuthor</author>
        <title>myTitle \tutorial 1\(edition 2)</title>
    </book>
</catalog>
... // some marker here to stop multi-line str

It seems like we need some markers for end-of-the-line to be able to keep
spaces/tabs in the end of line.

What about something like this. Two suported variants : first when we need
to keep spaces in the end of line, and second when we don't need
spaced(will be trimmed by parser)

#1 (parser should just take the text between first and last quote *as-is*)

let xml = "\
"<?xml version="1.0"?> " // yes, *I need* these spaces at the end
"<catalog>"
" <book id="myid" empty="">"
" <author>myAuthor</author>"
" <title>myTitle \tutorial 1\(edition 2)</title>"
" </book>"
"</catalog>"
"

#2 in this case we don't need any spaces/tabs in the end of lines(don't
care):
(parser takes all that is after | as-is but trims any trailing spaces/tabs
in lines to be clear in behaviour)

let xml = "\
><?xml version="1.0"?>
><catalog>
> <book id="myid" empty="">
> <author>myAuthor</author>
> <title>myTitle \tutorial 1\(edition 2)</title>
> </book>
></catalog>
"

Or these two could be combined in one(as-is between |..|) but I'm not sure:

let xml = "\
><?xml version="1.0"?> | // yes, I need these spaces
><catalog>| // we have to have closing symbol in this case in other lines
> <book id="myid" empty="">|
> <author>myAuthor</author>|
> <title>myTitle \tutorial 1\(edition 2)</title>|
> </book>|
></catalog>|
"

Gist: <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f&gt;

  Multiline string literals

  * Proposal: SE-NNNN
    <
https://github.com/apple/swift-evolution/blob/master/proposals/NNNN-name.md
>
  * Author(s): Brent Royal-Gordon <https://github.com/brentdax&gt;
  * Status: First Draft
  * Review manager: TBD

    <
https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#introduction
>Introduction

In Swift 2.2, the only means to insert a newline into a string literal is
the |\n| escape. String literals specified in this way are generally ugly
and unreadable. We propose a multiline string feature inspired by English
punctuation which is a straightforward extension of our existing string
literals.

Swift-evolution thread: multi-line string literals.
<
[swift-evolution] multi-line string literals.
>

    <
https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#draft-notes
>Draft
    Notes

  *

    This draft differs from the prototypes being thrown around on the list
    in that it specifies that comments should be treated as whitespace,
and
    that whitespace-only lines in the middle of a multiline string should
    be ignored. I'm not sure if this is feasible from a parsing
standpoint,
    and I'd like feedback from implementers on this point.

  *

    This draft also specifies diagnostics which should be included.
    Feedback on whether these are good choices would be welcome.

  *

    I am considering allowing you to put a backslash before the newline to
    indicate it should /not/ be included in the literal. In other words,
    this code:

    print("foo\
    "bar")

    Would print |"foobar"|. However, I think this should probably be
    proposed separately, because there may be a better way to do it.

  *

    I've listed only myself as an author because I don't want to put
anyone
    else's name to a document they haven't seen, but there are others who
    deserve to be listed (John Holdsworth at least). Let me know if you
    think you should be included.

    <
https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#motivation
>Motivation

As Swift begins to move into roles beyond app development, code which
needs
to generate text becomes a more important use case. Consider, for
instance,
generating even a small XML string:

let xml = "<?xml version=\"1.0\"?>\n<catalog>\n\t<book id=\"bk101\"
empty=\"\">\n\t\t<author>\(author)</author>\n\t</book>\n</catalog>"

The string is practically unreadable, its structure drowned in escapes and
run-together characters; it looks like little more than line noise. We can
improve its readability somewhat by concatenating separate strings for
each
line and using real tabs instead of |\t| escapes:

let xml = "<?xml version=\"1.0\"?>\n" +
          "<catalog>\n" +
          " <book id=\"bk101\" empty=\"\">\n" +
          " <author>\(author)</author>\n" +
          " </book>\n" +
          "</catalog>"

However, this creates a more complex expression for the type checker, and
there's still far more punctuation than ought to be necessary. If the most
important goal of Swift is making code readable, this kind of code falls
far short of that goal.

    <
https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#proposed-solution
>Proposed
    solution

We propose that, when Swift is parsing a string literal, if it reaches the
end of the line without encountering an end quote, it should look at the
next line. If it sees a quote mark there (a "continuation quote"), the
string literal contains a newline and then continues on that line.
Otherwise, the string literal is unterminated and syntactically invalid.

Our sample above could thus be written as:

let xml = "<?xml version=\"1.0\"?>
"<catalog>
          " <book id=\"bk101\" empty=\"\">
" <author>\(author)</author>
          " </book>
"</catalog>"

(Note that GitHub is applying incorrect syntax highlighting to this code
sample, because it's applying Swift 2 rules.)

This format's unbalanced quotes might strike some programmers as strange,
but it attempts to mimic the way multiple lines are quoted in English
prose. As an English Stack Exchange answer illustrates
<punctuation - Why does the multi-paragraph quotation rule exist? - English Language & Usage Stack Exchange

    “That seems like an odd way to use punctuation,” Tom said. “What harm
    would there be in using quotation marks at the end of every
paragraph?”

    “Oh, that’s not all that complicated,” J.R. answered. “If you closed
    quotes at the end of every paragraph, then you would need to
reidentify
    the speaker with every subsequent paragraph.

    “Say a narrative was describing two or three people engaged in a
    lengthy conversation. If you closed the quotation marks in the
previous
    paragraph, then a reader wouldn’t be able to easily tell if the
    previous speaker was extending his point, or if someone else in the
    room had picked up the conversation. By leaving the previous
    paragraph’s quote unclosed, the reader knows that the previous speaker
    is still the one talking.”

    “Oh, that makes sense. Thanks!”

Similarly, omitting the ending quotation mark tells the code's reader (and
compiler) that the literal continues on the next line, while including the
continuation quote reminds the reader (and compiler) that this line is
part
of a string literal.

      <
https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#benefits-of-continuation-quotes
>Benefits
      of continuation quotes

It would be simpler to not require continuation quotes, so why are they
required by this proposal? There are three reasons:

1.

    *They help the compiler pinpoint errors in string literal
    delimiting.* If continuation quotes were not required, then a missing
    end quote would be interpreted as a multiline string literal. This
    string literal would continue until the compiler encountered either
    another quote mark—perhaps at the site of another string literal or in
    a comment—or the end of the file. In either case, the compiler could
at
    best only indicate the start of the runaway string literal; in
    pathological cases (for instance, if the next string literal
    was |"+"|), it might not even be able to do that properly.

    With continuation quotes required, if you forget to include an end
    quote, the compiler can tell that you did not intend to create a
    multiline string and flag the line that actually has the problem. It
    can also provide immediately actionable fix-it assistance. The fact
    that there is a redundant indication on each line of the programmer's
    intent to include that line in a multiline quote allows the compiler
to
    guess the meaning of the code.

2.

    *They separate indentation from the string's contents.* Without
    continuation quotes, there would be no obvious indication of whether
    whitespace at the start of the line was intended to indent the string
    literal so it matched the surrounding code, or whether that whitespace
    was actually meant to be included in the resulting string. Multiline
    string literals would either have to put subsequent lines against the
    left margin, or apply error-prone heuristics to try to guess which
    whitespace was indentation and which was string literal content.

3.

    *They improve the ability to quickly recognize the literal.* The |"|
on
    each line serves as an immediately obvious indication that the line is
    part of a string literal, not code, and the row of |"| characters in a
    well-formatted file allows you to quickly scan up and down the file to
    see the extent of the literal.

    <
https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#detailed-design
>Detailed
    design

When Swift is parsing a string literal and reaches the end of a line
without finding a closing quote, it examines the next line, applying the
following rules:

1.

    If the next line is all whitespace, it is ignored; Swift moves on to
    the line afterward, applying these rules again.

2.

    If the next line begins with whitespace followed by a continuation
    quote, then the string literal contains a newline followed by the
    contents of the string literal starting on that line. (This line may
    itself have no closing quote, in which case the same rules apply to
the
    line which follows.)

3.

    If the next line contains anything else, Swift raises a syntax error
    for an unterminated string literal. This syntax error should offer two
    fix-its: one to close the string literal at the end of the current
    line, and one to include the next line in the string literal by
    inserting a continuation quote.

Rules 1 and 2 should treat comments as though they are whitespace; this
allows you to comment out individual lines in a multiline string literal.
(However, commenting out the last line of the string literal will still
make it unterminated, so you don't have a completely free hand in
commenting.)

    <
https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#impact-on-existing-code
>Impact
    on existing code

Failing to close a string literal before the end of the line is currently
a
syntax error, so no valid Swift code should be affected by this change.

    <
https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#alternatives-considered
>Alternatives
    considered

      <
https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#requiring-no-continuation-character
>Requiring
      no continuation character

The main alternative is to not require a continuation quote, and simply
extend the string literal from the starting quote to the ending quote,
including all newlines between them. For example:

let xml = "<?xml version=\"1.0\"?>
<catalog>
<book id=\"bk101\" empty=\"\">
<author>\(author)</author>
</book>
</catalog>"

This has several advantages:

1.

    It is simpler.

2.

    It is less offensive to programmers' sensibilities (since there are no
    unmatched |"| characters).

3.

    It does not require that you edit the string literal to insert a
    continuation quote in each line.

Balanced against the advantages, however, is the loss of the improved
diagnostics, code formatting, and visual affordances mentioned in the
"Benefits of continuation quotes" section above.

In practice, we believe that editor support (such as "Paste as String
Literal" or "Convert to String Literal" commands) can make adding
continuation quotes less burdensome, while also providing other
conveniences like automatic escaping. We believe the other two factors are
outweighed by the benefits of continuation quotes.

      <
https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#use-a-different-delimiter-for-multiline-strings
>Use

      a different delimiter for multiline strings

The initial suggestion was that multiline strings should use a different
delimiter, |"""|, at the beginning and end of the string, with no
continuation characters between. This solution was rejected because it has
the same issues as the "no continuation character" solution, and because
it
was mixing two orthogonal issues (multiline strings and alternate
delimiters).

Another suggestion was to support a heredoc syntax, which would allow you
to specify a placeholder string literal on one line whose content begins
on
the next line, running until some arbitrary delimiter. For instance, if
Swift adopted Perl 5's syntax, it might support code like:

connection.sendString(<<"END")
<?xml version="1.0"?>
<catalog>
    <book id="bk101" empty="">
        <author>\(author)</author>
    </book>
</catalog>
END

In addition to the issues with the |"""| syntax, heredocs are complicated
both to explain and to parse, and are not a natural extension of Swift's
current string syntax.

Both of these suggestions address interesting issues with string literals,
solving compelling use cases. They're just not that good at fixing the
specific issue at hand. We might consider them in the future to address
those problems to which they are better suited.

      <
https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#fixing-other-string-literal-readability-issues
>Fixing
      other string literal readability issues

This proposal is narrowly aimed at multiline strings. It intentionally
doesn't tackle several other problems with string literals:

  *

    Reducing the amount of double-backslashing needed when working with
    regular expression libraries, Windows paths, source code generation,
    and other tasks where backslashes are part of the data.

  *

    Alternate delimiters or other strategies for writing strings
    with |"| characters in them.

  *

    String literals consisting of very long pieces of text which are best
    represented completely verbatim.

These are likely to be subjects of future proposals, though not
necessarily
during Swift 3.

This proposal also does not attempt to address regular expression
literals.
The members of the core team who are interested in regular expression
support have ambitions for that feature which put it out of scope for
Swift 3.

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

Hi Brent,

This is essentially the same solution I proposed way back in December: [swift-evolution] multi-line string literals

I still have the same reservations about copying and pasting. Copying a string into your code is going to require adding a continuation quote on every line. If the string being added has quotes itself, the process of adding continuation quotes is going to make the syntax highlighter go bonkers while they are being inserted.

Should we not have a master document that considers the pros and cons of many different solutions? I started writing one such treatise a few weeks ago, but I haven’t been able to finish it yet. Just being able to see all of the potential implementations compared in one place but provide some insight. I imagine that this a feature that won’t change once it’s implemented, so it’s important to get it right.

Tyler

···

On Apr 27, 2016, at 1:58 PM, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:

On Apr 27, 2016, at 1:52 AM, Brent Royal-Gordon <brent@architechies.com <mailto:brent@architechies.com>> wrote:

If you agree that these are all orthogonal pieces, then treat them as such: I’d suggest that you provide a proposal that just tackles the continuation string literals. This seems simple, and possible to get in for Swift 3.

I've gone ahead and drafted this proposal, with some small extensions and adjustments. See the "Draft Notes" section for details of what I've changed and what concerns I have.

Awesome. Some specific suggestions below, but feel free to iterate in a pull request if you prefer that.

<https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#introduction&gt;Introduction

In Swift 2.2, the only means to insert a newline into a string literal is the \n escape. String literals specified in this way are generally ugly and unreadable. We propose a multiline string feature inspired by English punctuation which is a straightforward extension of our existing string literals.

Swift-evolution thread: multi-line string literals. <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160418/015500.html&gt;I would suggest - right up front - pointing out that “heredoc” style syntaxes are another potential solution to this problem, but that they are heavier weight (and other tradeoffs). This proposal doesn’t attempt to address there heredoc usecase, but it also doesn’t preclude adding it. It is also mentioning up front that this is part of multi-part proposal to make string literals nicer, and point to the “possible future directions” section at the end.
<https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#draft-notes&gt;Draft Notes

This draft differs from the prototypes being thrown around on the list in that it specifies that comments should be treated as whitespace, and that whitespace-only lines in the middle of a multiline string should be ignored. I'm not sure if this is feasible from a parsing standpoint, and I'd like feedback from implementers on this point.

White space seems “implementable”, but I’m not sure that it is good. Visually, it would break up the string literal and make it less obviously a unit.

Comments on the same line as a string chunk should *not* be split out IMO, in:

   let s = “fooo // hello world
              “ nice to know you”

the “hello world” text should be included in the literal. I suppose it would be possible to allow comments on whitespace lines, but I don’t see a reason to do that. I’d suggest starting simple, since that could always be added down the road if there was great demand.

This draft also specifies diagnostics which should be included. Feedback on whether these are good choices would be welcome.

I’d just say that these are suggested diagnostics that can be word smithed later.

I am considering allowing you to put a backslash before the newline to indicate it should not be included in the literal. In other words, this code:

print("foo\
"bar")
Would print "foobar". However, I think this should probably be proposed separately, because there may be a better way to do it.

I don’t see a reason to do that. Why would this be helpful?

Benefits of continuation quotes

It would be simpler to not require continuation quotes,

I’d suggest being explicit here:

"It would be simpler to not require continuation quotes at the start of subsequent lines, "

Rules 1 and 2 should treat comments as though they are whitespace; this allows you to comment out individual lines in a multiline string literal. (However, commenting out the last line of the string literal will still make it unterminated, so you don't have a completely free hand in commenting.)

As I mentioned above, I’d suggest keeping the proposal minimal - that makes it more likely to be accepted since you’re removing something that the discussion could rathole on.

Impact on existing code

Failing to close a string literal before the end of the line is currently a syntax error, so no valid Swift code should be affected by this change.

I would add a “Potential Future Directions” section here, mention modifier characters, here doc, etc. That will help explain how this proposal fits into your broader plan, and address the question of “ok, your XML example looks a little better, but what’s with all the escaping?!??” :-)

This has several advantages:

It is simpler.

It is less offensive to programmers' sensibilities (since there are no unmatched " characters).

It does not require that you edit the string literal to insert a continuation quote in each line.

Balanced against the advantages, however, is the loss of the improved diagnostics, code formatting, and visual affordances mentioned in the "Benefits of continuation quotes" section above.

Just a writing observation, but by bulleting the advantages (and not bulleting the disadvantages) you’re making it look visually like the advantages are stronger or more important than the disadvantages.

<https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#use-a-different-delimiter-for-multiline-strings&gt;Use a different delimiter for multiline strings

The initial suggestion was that multiline strings should use a different delimiter, """, at the beginning and end of the string, with no continuation characters between.

Personally, I think that “”” could be the compelling heredoc designator we will also need. :-) It would certainly fit elegantly with modifier characters, the same way that “” does.

-Chris

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

Can this concept be dealt with my allowing a string file to be imported and
assigned to a string constant? All happening at compile time and using
#include type concept from C? It would tackle at least a reasonable subset
of the issue in a way that I think works better for source control, etc.

let xml = @stringfile("Foo/Bar/baz.xml");

···

On Wed, Apr 27, 2016 at 9:35 AM John Siracusa via swift-evolution < swift-evolution@swift.org> wrote:

On Wed, Apr 27, 2016 at 9:08 AM, Vladimir.S via swift-evolution < > swift-evolution@swift.org> wrote:

I expect to be able to have multiline text exactly *"as-is"* in my source
file. No escaping, no interpolation, etc. I believe this should be a target
of the proposal.

I also see this as one of the most important goals of any multi-line
string-handling proposal. The "no escapes required" syntax doesn't have to
be the only way to handle multi-line strings, but it should be one of the
available ways.

-John

P.S. - Secondarily (and broader than just multi-line strings) I think
there should also be a way to avoid backslash-itis in strings of all kinds
by providing some flexibility in string delimiters. But that's for another
thread…

Otherwise, I reject to see any reason to introduce anything new at this
area - we already can concatenate strings and place them on next line and
escape special characters.

In your proposal, you have to escape characters in your text, you need to
carefully modify the copy-pasted text to be allowed as correct multi-line
string. Also, what if I need to have spaces *at the end of string* ? Editor
can just trimmed them, and we can't clearly see them.

Personally I need to be able to have this(in some way) in my code:
(note this "\tuttorial" and "\(edition" - this is just text, I want to
have inside my xml)

let xml = ... // some marker to start the multi-line str
<?xml version="1.0"?>
<catalog>
    <book id="myid" empty="">
        <author>myAuthor</author>
        <title>myTitle \tutorial 1\(edition 2)</title>
    </book>
</catalog>
... // some marker here to stop multi-line str

It seems like we need some markers for end-of-the-line to be able to keep
spaces/tabs in the end of line.

What about something like this. Two suported variants : first when we
need to keep spaces in the end of line, and second when we don't need
spaced(will be trimmed by parser)

#1 (parser should just take the text between first and last quote *as-is*)

let xml = "\
"<?xml version="1.0"?> " // yes, *I need* these spaces at the end
"<catalog>"
" <book id="myid" empty="">"
" <author>myAuthor</author>"
" <title>myTitle \tutorial 1\(edition 2)</title>"
" </book>"
"</catalog>"
"

#2 in this case we don't need any spaces/tabs in the end of lines(don't
care):
(parser takes all that is after | as-is but trims any trailing
spaces/tabs in lines to be clear in behaviour)

let xml = "\
><?xml version="1.0"?>
><catalog>
> <book id="myid" empty="">
> <author>myAuthor</author>
> <title>myTitle \tutorial 1\(edition 2)</title>
> </book>
></catalog>
"

Or these two could be combined in one(as-is between |..|) but I'm not
sure:

let xml = "\
><?xml version="1.0"?> | // yes, I need these spaces
><catalog>| // we have to have closing symbol in this case in other lines
> <book id="myid" empty="">|
> <author>myAuthor</author>|
> <title>myTitle \tutorial 1\(edition 2)</title>|
> </book>|
></catalog>|
"

Gist: <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f
>

  Multiline string literals

  * Proposal: SE-NNNN
    <
https://github.com/apple/swift-evolution/blob/master/proposals/NNNN-name.md
>
  * Author(s): Brent Royal-Gordon <https://github.com/brentdax&gt;
  * Status: First Draft
  * Review manager: TBD

    <
https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#introduction
>Introduction

In Swift 2.2, the only means to insert a newline into a string literal is
the |\n| escape. String literals specified in this way are generally ugly
and unreadable. We propose a multiline string feature inspired by English
punctuation which is a straightforward extension of our existing string
literals.

Swift-evolution thread: multi-line string literals.
<
[swift-evolution] multi-line string literals.
>

    <
https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#draft-notes
>Draft
    Notes

  *

    This draft differs from the prototypes being thrown around on the
list
    in that it specifies that comments should be treated as whitespace,
and
    that whitespace-only lines in the middle of a multiline string should
    be ignored. I'm not sure if this is feasible from a parsing
standpoint,
    and I'd like feedback from implementers on this point.

  *

    This draft also specifies diagnostics which should be included.
    Feedback on whether these are good choices would be welcome.

  *

    I am considering allowing you to put a backslash before the newline
to
    indicate it should /not/ be included in the literal. In other words,
    this code:

    print("foo\
    "bar")

    Would print |"foobar"|. However, I think this should probably be
    proposed separately, because there may be a better way to do it.

  *

    I've listed only myself as an author because I don't want to put
anyone
    else's name to a document they haven't seen, but there are others who
    deserve to be listed (John Holdsworth at least). Let me know if you
    think you should be included.

    <
https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#motivation
>Motivation

As Swift begins to move into roles beyond app development, code which
needs
to generate text becomes a more important use case. Consider, for
instance,
generating even a small XML string:

let xml = "<?xml version=\"1.0\"?>\n<catalog>\n\t<book id=\"bk101\"
empty=\"\">\n\t\t<author>\(author)</author>\n\t</book>\n</catalog>"

The string is practically unreadable, its structure drowned in escapes
and
run-together characters; it looks like little more than line noise. We
can
improve its readability somewhat by concatenating separate strings for
each
line and using real tabs instead of |\t| escapes:

let xml = "<?xml version=\"1.0\"?>\n" +
          "<catalog>\n" +
          " <book id=\"bk101\" empty=\"\">\n" +
          " <author>\(author)</author>\n" +
          " </book>\n" +
          "</catalog>"

However, this creates a more complex expression for the type checker, and
there's still far more punctuation than ought to be necessary. If the
most
important goal of Swift is making code readable, this kind of code falls
far short of that goal.

    <
https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#proposed-solution
>Proposed
    solution

We propose that, when Swift is parsing a string literal, if it reaches
the
end of the line without encountering an end quote, it should look at the
next line. If it sees a quote mark there (a "continuation quote"), the
string literal contains a newline and then continues on that line.
Otherwise, the string literal is unterminated and syntactically invalid.

Our sample above could thus be written as:

let xml = "<?xml version=\"1.0\"?>
"<catalog>
          " <book id=\"bk101\" empty=\"\">
" <author>\(author)</author>
          " </book>
"</catalog>"

(Note that GitHub is applying incorrect syntax highlighting to this code
sample, because it's applying Swift 2 rules.)

This format's unbalanced quotes might strike some programmers as strange,
but it attempts to mimic the way multiple lines are quoted in English
prose. As an English Stack Exchange answer illustrates
<punctuation - Why does the multi-paragraph quotation rule exist? - English Language & Usage Stack Exchange

    “That seems like an odd way to use punctuation,” Tom said. “What harm
    would there be in using quotation marks at the end of every
paragraph?”

    “Oh, that’s not all that complicated,” J.R. answered. “If you closed
    quotes at the end of every paragraph, then you would need to
reidentify
    the speaker with every subsequent paragraph.

    “Say a narrative was describing two or three people engaged in a
    lengthy conversation. If you closed the quotation marks in the
previous
    paragraph, then a reader wouldn’t be able to easily tell if the
    previous speaker was extending his point, or if someone else in the
    room had picked up the conversation. By leaving the previous
    paragraph’s quote unclosed, the reader knows that the previous
speaker
    is still the one talking.”

    “Oh, that makes sense. Thanks!”

Similarly, omitting the ending quotation mark tells the code's reader
(and
compiler) that the literal continues on the next line, while including
the
continuation quote reminds the reader (and compiler) that this line is
part
of a string literal.

      <
https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#benefits-of-continuation-quotes
>Benefits
      of continuation quotes

It would be simpler to not require continuation quotes, so why are they
required by this proposal? There are three reasons:

1.

    *They help the compiler pinpoint errors in string literal
    delimiting.* If continuation quotes were not required, then a missing
    end quote would be interpreted as a multiline string literal. This
    string literal would continue until the compiler encountered either
    another quote mark—perhaps at the site of another string literal or
in
    a comment—or the end of the file. In either case, the compiler could
at
    best only indicate the start of the runaway string literal; in
    pathological cases (for instance, if the next string literal
    was |"+"|), it might not even be able to do that properly.

    With continuation quotes required, if you forget to include an end
    quote, the compiler can tell that you did not intend to create a
    multiline string and flag the line that actually has the problem. It
    can also provide immediately actionable fix-it assistance. The fact
    that there is a redundant indication on each line of the programmer's
    intent to include that line in a multiline quote allows the compiler
to
    guess the meaning of the code.

2.

    *They separate indentation from the string's contents.* Without
    continuation quotes, there would be no obvious indication of whether
    whitespace at the start of the line was intended to indent the string
    literal so it matched the surrounding code, or whether that
whitespace
    was actually meant to be included in the resulting string. Multiline
    string literals would either have to put subsequent lines against the
    left margin, or apply error-prone heuristics to try to guess which
    whitespace was indentation and which was string literal content.

3.

    *They improve the ability to quickly recognize the literal.* The |"|
on
    each line serves as an immediately obvious indication that the line
is
    part of a string literal, not code, and the row of |"| characters in
a
    well-formatted file allows you to quickly scan up and down the file
to
    see the extent of the literal.

    <
https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#detailed-design
>Detailed
    design

When Swift is parsing a string literal and reaches the end of a line
without finding a closing quote, it examines the next line, applying the
following rules:

1.

    If the next line is all whitespace, it is ignored; Swift moves on to
    the line afterward, applying these rules again.

2.

    If the next line begins with whitespace followed by a continuation
    quote, then the string literal contains a newline followed by the
    contents of the string literal starting on that line. (This line may
    itself have no closing quote, in which case the same rules apply to
the
    line which follows.)

3.

    If the next line contains anything else, Swift raises a syntax error
    for an unterminated string literal. This syntax error should offer
two
    fix-its: one to close the string literal at the end of the current
    line, and one to include the next line in the string literal by
    inserting a continuation quote.

Rules 1 and 2 should treat comments as though they are whitespace; this
allows you to comment out individual lines in a multiline string literal.
(However, commenting out the last line of the string literal will still
make it unterminated, so you don't have a completely free hand in
commenting.)

    <
https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#impact-on-existing-code
>Impact
    on existing code

Failing to close a string literal before the end of the line is
currently a
syntax error, so no valid Swift code should be affected by this change.

    <
https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#alternatives-considered
>Alternatives
    considered

      <
https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#requiring-no-continuation-character
>Requiring
      no continuation character

The main alternative is to not require a continuation quote, and simply
extend the string literal from the starting quote to the ending quote,
including all newlines between them. For example:

let xml = "<?xml version=\"1.0\"?>
<catalog>
<book id=\"bk101\" empty=\"\">
<author>\(author)</author>
</book>
</catalog>"

This has several advantages:

1.

    It is simpler.

2.

    It is less offensive to programmers' sensibilities (since there are
no
    unmatched |"| characters).

3.

    It does not require that you edit the string literal to insert a
    continuation quote in each line.

Balanced against the advantages, however, is the loss of the improved
diagnostics, code formatting, and visual affordances mentioned in the
"Benefits of continuation quotes" section above.

In practice, we believe that editor support (such as "Paste as String
Literal" or "Convert to String Literal" commands) can make adding
continuation quotes less burdensome, while also providing other
conveniences like automatic escaping. We believe the other two factors
are
outweighed by the benefits of continuation quotes.

      <
https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#use-a-different-delimiter-for-multiline-strings
>Use

      a different delimiter for multiline strings

The initial suggestion was that multiline strings should use a different
delimiter, |"""|, at the beginning and end of the string, with no
continuation characters between. This solution was rejected because it
has
the same issues as the "no continuation character" solution, and because
it
was mixing two orthogonal issues (multiline strings and alternate
delimiters).

Another suggestion was to support a heredoc syntax, which would allow you
to specify a placeholder string literal on one line whose content begins
on
the next line, running until some arbitrary delimiter. For instance, if
Swift adopted Perl 5's syntax, it might support code like:

connection.sendString(<<"END")
<?xml version="1.0"?>
<catalog>
    <book id="bk101" empty="">
        <author>\(author)</author>
    </book>
</catalog>
END

In addition to the issues with the |"""| syntax, heredocs are complicated
both to explain and to parse, and are not a natural extension of Swift's
current string syntax.

Both of these suggestions address interesting issues with string
literals,
solving compelling use cases. They're just not that good at fixing the
specific issue at hand. We might consider them in the future to address
those problems to which they are better suited.

      <
https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#fixing-other-string-literal-readability-issues
>Fixing
      other string literal readability issues

This proposal is narrowly aimed at multiline strings. It intentionally
doesn't tackle several other problems with string literals:

  *

    Reducing the amount of double-backslashing needed when working with
    regular expression libraries, Windows paths, source code generation,
    and other tasks where backslashes are part of the data.

  *

    Alternate delimiters or other strategies for writing strings
    with |"| characters in them.

  *

    String literals consisting of very long pieces of text which are best
    represented completely verbatim.

These are likely to be subjects of future proposals, though not
necessarily
during Swift 3.

This proposal also does not attempt to address regular expression
literals.
The members of the core team who are interested in regular expression
support have ambitions for that feature which put it out of scope for
Swift 3.

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

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

Sorry, but I don't see that your suggestion is "lot less easy to understand what's going on" in compare to what we have now.

We have :

let xml = "<?xml version=\"1.0\"?>\n" +
           "<catalog>\n" +
           " <book id=\"bk101\" empty=\"\">\n" +
           " <author>\(author)</author>\n" +
           " </book>\n" +
           "</catalog>"

You suggest :

let xml = "<?xml version=\"1.0\"?>
           "<catalog>
           " <book id=\"bk101\" empty=\"\">
           " <author>\(author)</author>
           " </book>
           "</catalog>"

I can't feel this like much more better because of the same escaping of special chars. I don't see much problems in \n" and + in first(current) variant. I just don't understand what such kind of multiline we need for, so we want to introduce a new 'feature' in language. I don't feel such a small improvement worth to be implemented. Just my opinion, probably I'm not right.

My suggestion(one of) :

let xml = "\
"<?xml version="1.0"?>
"<catalog>
" <book id="myid" empty="">
" <author>myAuthor</author>
" <title>myTitle \tutorial 1\(edition 2)</title>
" </book>
"</catalog>
/"

Pros:
* multi-line
* text as-is(with just " at start), no escaping, all characters are allowed
* " at the start says it is a string
* begins with "\ - clearly saying it is a start of special string
* ends with /" - clearly saying "end of the special string"
Cons(but actually this is 'by design' of the feature for text as-is):
* not able to explicitly have 'tab' symbol (was \t)
* not able to have other escaped chars like \n
* not able to have string interpolation.

···

On 27.04.2016 17:33, Brent Royal-Gordon wrote:

Otherwise, I reject to see any reason to introduce anything new at
this area - we already can concatenate strings and place them on next
line and escape special characters.

Sure, but it's a lot less easy to understand what's going on. See the
examples in the "Motivation" and "Proposed solution" sections.

White space seems “implementable”, but I’m not sure that it is good. Visually, it would break up the string literal and make it less obviously a unit.

Comments on the same line as a string chunk should *not* be split out IMO, in:

   let s = “fooo // hello world
              “ nice to know you”

the “hello world” text should be included in the literal. I suppose it would be possible to allow comments on whitespace lines, but I don’t see a reason to do that. I’d suggest starting simple, since that could always be added down the road if there was great demand.

What I'm actually suggesting is that comments *before* the continuing quote would be honored without terminating the literal:

let xml = "<?xml version=\"1.0\"?>
          "<catalog>
          " <book id=\"bk101\" empty=\"\">
// " <author>\(author)</author>
          " </book>
          "</catalog>"

A // or /* after the continuing quote would still be part of the literal.

I'm preparing a second draft without that feature, though, so if you still think it's a bad idea, I'll drop it.

···

--
Brent Royal-Gordon
Architechies

Awesome. Some specific suggestions below, but feel free to iterate in a pull request if you prefer that.

I've adopted these suggestions in some form, though I also ended up rewriting the explanation of why the feature was designed as it is and fusing it with material from "Alternatives considered".

(Still not sure who I should list as a co-author. I'm currently thinking John, Tyler, and maybe Chris? Who's supposed to go there?)

Multiline string literals

Proposal: SE-NNNN <https://github.com/apple/swift-evolution/blob/master/proposals/NNNN-name.md&gt;
Author(s): Brent Royal-Gordon <https://github.com/brentdax&gt;
Status: Second Draft
Review manager: TBD
<https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#introduction&gt;Introduction

In Swift 2.2, the only means to insert a newline into a string literal is the \n escape. String literals specified in this way are generally ugly and unreadable. We propose a multiline string feature inspired by English punctuation which is a straightforward extension of our existing string literals.

This proposal is one step in a larger plan to improve how string literals address various challenging use cases. It is not meant to solve all problems with escaping, nor to serve all use cases involving very long string literals. See the "Future directions for string literals in general" section for a sketch of the problems we ultimately want to address and some ideas of how we might do so.

Swift-evolution threads: multi-line string literals. (April) <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160418/015500.html&gt;, multi-line string literals (December) <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151214/002349.html&gt;
<https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#draft-notes&gt;Draft Notes

Removes the comment feature, which was felt to be an unnecessary complication. This and the backslash feature have been listed as future directions.

Loosens the specification of diagnostics, suggesting instead of requiring fix-its.

Splits a "Rationale" section out of the "Proposed solution" section.

Adds extensive discussion of other features which wold combine with this one.

I've listed only myself as an author because I don't want to put anyone else's name to a document they haven't seen, but there are others who deserve to be listed (John Holdsworth at least). Let me know if you think you should be included.

<https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#motivation&gt;Motivation

As Swift begins to move into roles beyond app development, code which needs to generate text becomes a more important use case. Consider, for instance, generating even a small XML string:

let xml = "<?xml version=\"1.0\"?>\n<catalog>\n\t<book id=\"bk101\" empty=\"\">\n\t\t<author>\(author)</author>\n\t</book>\n</catalog>"
The string is practically unreadable, its structure drowned in escapes and run-together lines; it looks like little more than line noise. We can improve its readability somewhat by concatenating separate strings for each line and using real tabs instead of \t escapes:

let xml = "<?xml version=\"1.0\"?>\n" +
          "<catalog>\n" +
          " <book id=\"bk101\" empty=\"\">\n" +
          " <author>\(author)</author>\n" +
          " </book>\n" +
          "</catalog>"
However, this creates a more complex expression for the type checker, and there's still far more punctuation than ought to be necessary. If the most important goal of Swift is making code readable, this kind of code falls far short of that goal.

<https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#proposed-solution&gt;Proposed solution

We propose that, when Swift is parsing a string literal, if it reaches the end of the line without encountering an end quote, it should look at the next line. If it sees a quote at the beginning (a "continuation quote"), the string literal contains a newline and then continues on that line. Otherwise, the string literal is unterminated and syntactically invalid.

Our sample above could thus be written as:

let xml = "<?xml version=\"1.0\"?>
          "<catalog>
          " <book id=\"bk101\" empty=\"\">
          " <author>\(author)</author>
          " </book>
          "</catalog>"
If the second or subsequent lines had not begun with a quotation mark, or the trailing quotation mark after the </catalog>tag had not been included, Swift would have emitted an error.

<https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#rationale&gt;Rationale

This design is rather unusual, and it's worth pausing a moment to explain why it has been chosen.

The traditional design for this feature, seen in languages like Perl and Python, simply places one delimiter at the beginning of the literal and another at the end. Individual lines in the literal are not marked in any way.

We think continuation quotes offer several important advantages over the traditional design:

They help the compiler pinpoint errors in string literal delimiting. Traditional multiline strings have a serious weakness: if you forget the closing quote, the compiler has no idea where you wanted the literal to end. It simply continues on until the compiler encounters another quote (or the end of the file). If you're lucky, the text after that quote is not valid code, and the resulting error will at least point you to the next string literal in the file. If you're unlucky, you'll get a seemingly unrelated error several literals later, an unbalanced brace error at the end of the file, or perhaps even code that compiles but does something totally wrong.

(This is not a minor concern. Many popular languages, including C and Swift 2, specifically reject newlines in string literals to prevent this from happening.)

Continuation quotes provide the compiler with redundant information about your intent. If you forget a closing quote, the continuation quotes give the compiler a very good idea of where you meant to put it. The compiler can point you to (or at least very near) the end of the literal, where you want to insert the quote, rather than showing you the beginning of the literal or even some unrelated error later in the file that was caused by the missing quote.

Temporarily unclosed literals don't make editors go haywire. The syntax highlighter has the same trouble parsing half-written, unclosed traditional quotes that the compiler does: It can't tell where the literal is supposed to end and the code should begin. It must either apply heuristics to try to guess where the literal ends, or incorrectly color everything between the opening quote and the next closing quote as a string literal. This can cause the file's coloring to alternate distractingly between "string literal" and "running code".

Continuation quotes give the syntax highlighter enough context to guess at the correct coloration, even when the string isn't complete yet. Lines with a continuation quote are literals; lines without are code. At worst, the syntax highlighter might incorrectly color a few characters at the end of a line, rather than the remainder of the file.

They separate indentation from the string's contents. Traditional multiline strings usually include all of the content between the start and end delimiters, including leading whitespace. This means that it's usually impossible to indent a multiline string, so including one breaks up the flow of the surrounding code, making it less readable. Some languages apply heuristics or mode switches to try to remove indentation, but like all heuristics, these are mistake-prone and murky.

Continuation quotes neatly avoid this problem. Whitespace before the continuation quote is indentation used to format the source code; whitespace after the continuation quote is part of the string literal. The interpretation of the code is perfectly clear to both compiler and programmer.

They improve the ability to quickly recognize the literal. Traditional multiline strings don't provide much visual help. To find the end, you must visually scan until you find the matching delimiter, which may be only one or a few characters long. When looking at a random line of source, it can be hard to tell at a glance whether it's code or literal. Syntax highlighting can help with these issues, but it's often unreliable, especially with advanced, idiosyncratic string literal features like multiline strings.

Continuation quotes solve these problems. To find the end of the literal, just scan down the column of continuation characters until they end. To figure out if a given line of source is part of a literal, just see if it starts with a quote mark. The meaning of the source becomes obvious at a glance.

Nevertheless, the traditional design does has a few advantages:

It is simpler. Although continuation quotes are more complex, we believe that the advantages listed above pay for that complexity.

There is no need to edit the intervening lines to add continuation quotes. While the additional effort required to insert continuation quotes is an important downside, we believe that tool support, including both compiler fix-its and perhaps editor support for commands like "Paste as String Literal", can address this issue. In some editors, new features aren't even necessary; TextMate, for instance, lets you insert a character on several lines simultaneously. And new tool features could also address other issues like escaping embedded quotes.

Naïve syntax highlighters may have trouble understanding this syntax. This is true, but naïve syntax highlighters generally have terrible trouble with advanced string literal constructs; some struggle with even basic ones. While there are some designs (like Python's """ strings) which trick some syntax highlighters into working some of the time with some contents, we don't think this occasional, accidental compatibility is a big enough gain to justify changing the design.

It looks funny—quotes should always be in matched pairs. We aren't aware of another programming language which uses unbalanced quotes in string literals, but there is one very important precedent for this kind of formatting: natural languages. English, for instance, uses a very similar format for quoting multiple lines of dialog by the same speaker. As an English Stack Exchange answer illustrates <punctuation - Why does the multi-paragraph quotation rule exist? - English Language & Usage Stack Exchange

“That seems like an odd way to use punctuation,” Tom said. “What harm would there be in using quotation marks at the end of every paragraph?”

“Oh, that’s not all that complicated,” J.R. answered. “If you closed quotes at the end of every paragraph, then you would need to reidentify the speaker with every subsequent paragraph.

“Say a narrative was describing two or three people engaged in a lengthy conversation. If you closed the quotation marks in the previous paragraph, then a reader wouldn’t be able to easily tell if the previous speaker was extending his point, or if someone else in the room had picked up the conversation. By leaving the previous paragraph’s quote unclosed, the reader knows that the previous speaker is still the one talking.”

“Oh, that makes sense. Thanks!”
In English, omitting the ending quotation mark tells the text's reader that the quote continues on the next line, while including a quotation mark at the beginning of the next line reminds the reader that they're in the middle of a quote.

Similarly, in this proposal, omitting the ending quotation mark tells the code's reader (and compiler) that the string literal continues on the next line, while including a quotation mark at the beginning of the next line reminds the reader (and compiler) that they're in the middle of a string literal.

On balance, we think continuation quotes are the best design for this problem.

<https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#detailed-design&gt;Detailed design

When Swift is parsing a string literal and reaches the end of a line without finding a closing quote, it examines the next line, applying the following rules:

If the next line begins with whitespace followed by a continuation quote, then the string literal contains a newline followed by the contents of the string literal starting on that line. (This line may itself have no closing quote, in which case the same rules apply to the line which follows.)

If the next line contains anything else, Swift raises a syntax error for an unterminated string literal.

The exact error messages and diagnostics provided are left to the implementers to determine, but we believe it should be possible to provide two fix-its which will help users learn the syntax and correct string literal mistakes:

Insert " at the end of the current line to terminate the quote.

Insert " at the beginning of the next line (with some indentation heuristics) to continue the quote on the next line.

<https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#impact-on-existing-code&gt;Impact on existing code

Failing to close a string literal before the end of the line is currently a syntax error, so no valid Swift code should be affected by this change.

<https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#future-directions-for-multiline-string-literals&gt;Future directions for multiline string literals

We could permit comments before encountering a continuation quote to be counted as whitespace, and permit empty lines in the middle of string literals. This would allow you to comment out whole lines in the literal.

We could allow you to put a trailing backslash on a line to indicate that the newline isn't "real" and should be omitted from the literal's contents.

<https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#future-directions-for-string-literals-in-general&gt;Future directions for string literals in general

There are other issues with Swift's string handling which this proposal intentionally does not address:

Reducing the amount of double-backslashing needed when working with regular expression libraries, Windows paths, source code generation, and other tasks where backslashes are part of the data.

Alternate delimiters or other strategies for writing strings with " characters in them.

Accommodating code formatting concerns like hard wrapping and commenting.

String literals consisting of very long pieces of text which are best represented completely verbatim, with minimal alteration.

This section briefly outlines some future proposals which might address these issues. Combined, we believe they would address most of the string literal use cases which Swift is currently not very good at.

Please note that these are simply sketches of hypothetical future designs; they may radically change before proposal, and some may never be proposed at all. Many, perhaps most, will not be proposed for Swift 3. We are sketching these designs not to propose and refine these features immediately, but merely to show how we think they might be solved in ways which complement this proposal.

<https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#string-literal-modifiers&gt;String literal modifiers

A string literal modifier is a cluster of identifier characters which goes before a string literal and adjusts the way it is parsed. Modifers only alter the interpretation of the text in the literal, not the type of data it produces; for instance, there will never be something like the UTF-8/UTF-16/UTF-32 literal modifiers in C++. Uppercase characters enable a feature; lowercase characters disable a feature.

Modifiers can be attached to both single-line and multiline literals, and could also be attached to other literal syntaxes which might be introduced in the future. When used with multiline strings, only the starting quote needs to carry the modifiers, not the continuation quotes.

Modifiers are an extremely flexible feature which can be used for many proposes. Of the ideas listed below, we believe the e modifier is an urgent addition which should be included in Swift 3 if at all possible; the others are less urgent and most of them could be deferred, or at least added later if time allows.

Escape disabling: e"\\\" (string with three backslash characters)

Fine-grained escape disabling: i"\(foo)\n" (the string \(foo) followed by a newline); eI"\(foo)\n" (the contents of foo followed by the string \n), b"\w+\n" (the string \w+ followed by a newline)

Alternate delimiters: _ has no lowercase form, so it could be used to allow strings with internal quotes: _"print("Hello, world!")"_, __"print("Hello, world!")"__, etc.

Whitespace normalization: changes all runs of whitespace in the literal to single space characters; this would allow you to use multiline strings purely to improve code formatting.

alert.informativeText =
    W"\(appName) could not typeset the element “\(title)” because
     "it includes a link to an element that has been removed from this
     "book."
Localization:

alert.informativeText =
    LW"\(appName) could not typeset the element “\(title)” because
      "it includes a link to an element that has been removed from this
      "book."
Comments: Embedding comments in string literals might be useful for literals containing regular expressions or other code.

Eventually, user-specified string modifiers could be added to Swift, perhaps as part of a hygienic macro system. It might also become possible to change the default modifiers applied to literals in a particular file or scope.

<https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#heredocs-or-other-verbatim-string-literal-features&gt;Heredocs or other "verbatim string literal" features

Sometimes it really is best to just splat something else down in the middle of a file full of Swift source code. Maybe the file is essentially a template and the literals are a majority of the code's contents, or maybe you're writing a code generator and just want to get string data into it with minimal fuss, or maybe people unfamiliar with Swift need to be able to edit the literals. Whatever the reason, the normal string literal syntax is just too burdensome.

One approach to this problem is heredocs. A heredoc allows you to put a placeholder for a literal on one line; the contents of the literal begin on the next line, running up to some delimiter. It would be possible to put multiple placeholders in a single line, and to apply string modifiers to them.

In Swift, this might look like:

print(#to("---") + e#to("END"))
It was a dark and stormy \(timeOfDay) when

···

---
the Swift core team invented the \(interpolation) syntax.
END
Another possible approach would be to support traditional multiline string literals bounded by a different delimiter, like """. This might look like:

print("""
It was a dark and stormy \(timeOfDay) when
""" + e"""
the Swift core team invented the \(interpolation) syntax.
""")
Although heredocs could make a good addition to Swift eventually, there are good reasons to defer them for now. Please see the "Alternatives considered" section for details.

<https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#first-class-regular-expressions&gt;First\-class regular expressions

Members of the core team are interested in regular expressions, but they don't want to just build a literal that wraps PCRE or libicu; rather, they aim to integrate regexes into the pattern matching system and give them a deep, Perl 6-style rethink. This would be a major effort, far beyond the scope of Swift 3.

In the meantime, the e modifier and perhaps other string literal modifiers will make it easier to specify regular expressions in string literals for use with NSRegularExpression and other libraries accessible from Swift.

<https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#alternatives-considered&gt;Alternatives considered

<https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#requiring-no-continuation-character&gt;Requiring no continuation character

The main alternative is to not require a continuation quote, and simply extend the string literal from the starting quote to the ending quote, including all newlines between them. For example:

let xml = "<?xml version=\"1.0\"?>
<catalog>
    <book id=\"bk101\" empty=\"\">
        <author>\(author)</author>
    </book>
</catalog>"
This alternative is extensively discussed in the "Rationale" section above.

<https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#skip-multiline-strings-and-just-support-heredocs&gt;Skip multiline strings and just support heredocs

There are definitely cases where a heredoc would be a better solution, such as generated code or code which is mostly literals with a little Swift sprinkled around. On the other hand, there are also cases where multiline strings are better: short strings in code which is meant to be read. If a single feature can't handle them both well, there's no shame in supporting the two features separately.

It makes sense to support multiline strings first because:

They extend existing syntax instead of introducing new syntax.

They are much easier to parse; heredocs require some kind of mode in the parser which kicks in at the start of the next line, whereas multiline string literals can be handled in the lexer.

As discussed in "Rationale", they offer better diagnostics, code formatting, and visual scannability.

<https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#use-a-different-delimiter-for-multiline-strings&gt;Use a different delimiter for multiline strings

The initial suggestion was that multiline strings should use a different delimiter, """, at the beginning and end of the string, with no continuation characters between. Like heredocs, this might be a good alternative for certain use cases, but it has the same basic flaws as the "no continuation character" solution.

--
Brent Royal-Gordon
Architechies

My only reservation is what external editors will make of these strings as there
is no precedent in another programming language I am aware of.

I understand what you mean. The `e` syntax is similar to some things in other languages (C# uses `@`, Python uses `r`, etc.), but so far as I'm aware, we're breaking new ground with the other stuff.

On the other hand, we'd hardly be the first language to do exotic things for multiline strings or alternate delimiters. I think people who use general purpose text editors are used to this stuff not always working quite right.

I’ve updated the "reference toolchain" and PR for testing and review.

http://johnholdsworth.com/swift-LOCAL-2016-05-01-a-osx.tar.gz
[Parse] Adjust Lexer to allow Multi-line string literals by johnno1962 · Pull Request #2275 · apple/swift · GitHub

Thank you. It is super-cool to be able to take these things out for a test drive.

This implementation still contains the “e” modifier as an example of how they
would be lexed (which I’ll remove before submission as it is outside the scope
of this proposal)

I left a line comment in the pull request about how it's been implemented, but this is great for testing the ergonomics.

I'm having trouble getting the `e` modifier to work as advertised, at least for the sequence `\\`. For example, `print(e"\\\\")` prints two backslashes, and `print(e"\\\")` seems to try to escape the string literal. I'm currently envisioning `e` as disabling *all* backslash escapes, so these behaviors wouldn't be appropriate. It also looks like interpolation is still enabled in `e` strings.

Since other things like `print(e"\w+")` work just fine, I'm guessing this is a bug in the proposal's sketches (not being clear enough about the expected behavior), not your code.

I've written a gist with some tests to show how I expect things to work:

  https://gist.github.com/brentdax/be3c032bc7e0c101d7ba8b72cd1a692e

I haven't looked into Stdlib's testing tools, so I wrote a chunk of code that uses an old Perl testing format I know by heart. If these tests look useful, I'd be happy to help adapt them to the Swift test suite.

If you want to look instead of run, the actual tests start around line 100. As I write this, it currently has three failures and two to-do tests (the todos use `e` and `_` at the same time). There are also a couple examples of expected compiler errors at the bottom of the file that you can uncomment.

and one new feature that \ before a newline ignores the newline.

This is in the "Future directions for multiline strings" section of the proposal. Having implemented this, how do you feel about it? Does it seem like such a no-brainer that we should just incorporate it into the proposal?

In this implementation modifiers can only be applied to the first segment of the literal.

That is how I imagine this would work. For instance:

  let swiftCode = e_"print("hello, world!\n")
                               "print("How are you today?")"_

Note that the continuation quote on the second line doesn't say `e` or `_`; it is merely a reminder that we are parsing a string literal, and doesn't need those things.

(If we wanted to, of course, we *could* require them. But I don't see much benefit—it would make changing modifiers burdensome.)

···

--
Brent Royal-Gordon
Architechies

Hi John,

in truth, your work is what gave me the idea of creating a separate parsing path now (what I called lexStringMultilineLiteral() )exactly for the two points you make:

it is possible/straightforward to ‘tweak’ the current lexing code to get something going as you proved it
using the default string literal recognition mechanism binds us to have to ‘wait’ a bit in order to figure which kind of string literal we are dealing with (single/multi line)

I poorly described that and apologize for it. So there is now doubt that with enough small alterations, the current parser will be made better, smarter, … my point is that this may not be desirable, and in fact be like the song of a siren calling in the wrong direction?!

Taking today the step to split the parsing into 2 separate paths has some implication on the features that can be devised in the future, without IMO ever having to revisit this fundamental split. However, I will also be the first to recognize that if there is no long term appeal for content type tagging or macros or custom formatters/verifiers, then there is indeed no need to split the path today, or ever for that matter.

But if these make sense for 3 and more likely past 3, then one can easily see today that a split is likely going to make these features a lot easier to implement then, and if it is the right path then and we can see it today, then IMO it stands to reason to build it in today (per the team’s development doctrine that features be as much as possible split between the preliminary enablement steps and the specifics of the features) provided that it does not commit us to anything today that has not and cannot yet be decided, and considering how it will on the other hand facilitate more exploratory work in the community with minimal burden to the core team. Considering the length of this thread and sophistication of some of the interventions, there is little doubt in my mind that this will not be a simple consensus builder, which will IMO only increase the value of having a common extension ground for prototypes.

The names I proposed are only the result of trying to make the additions simple by reference to the surrounding code, while trying to minimize the intersection between current and new code. To that effect my ongoing implementation is based on a couple of changes in lexImpl(), the rest being isolated inside new methods. But fundamentally the question I am presenting is about the

long term usability of a contents tagging possibility (does not have to be done now, but will IMO be easier that way)
workload management utilitarian aspect of a simple base split today for parallel explorations and easier merges along the way

The short term how is only one of the possible ways, which only makes sense based on the long term term direction string literals will take.

Best regards, and thank you John for showing me where to start.

LM/

···

On May 1, 2016, at 7:15 PM, John Holdsworth <mac@johnholdsworth.com> wrote:

Thanks Brent for pulling together the proposal and summarising this thread.

I have to say I still feel most drawn to your “continuation quotes” idea and after
some thought the “_” modifier for _”strings”with”quotes”_ also seems sensible.
Most of all, for me the appeal of these approaches is their absolute simplicity.
My only reservation is what external editors will make of these strings as there
is no precedent in another programming language I am aware of.

I’ve updated the "reference toolchain" and PR for testing and review.

http://johnholdsworth.com/swift-LOCAL-2016-05-01-a-osx.tar.gz
[Parse] Adjust Lexer to allow Multi-line string literals by johnno1962 · Pull Request #2275 · apple/swift · GitHub

This implementation still contains the “e” modifier as an example of how they
would be lexed (which I’ll remove before submission as it is outside the scope
of this proposal) and one new feature that \ before a newline ignores the newline.
In this implementation modifiers can only be applied to the first segment of the literal.

This makes the following strings valid to my mind:

        let xml = "\
            "<?xml version=\"1.0\"?>
            "<catalog>
            " <book id=\"bk101\" empty=\"\">
            " <author>\(author)</author>
            " <title>XML Developer's Guide</title>
            " <genre>Computer</genre>
            " <price>44.95</price>
            " <publish_date>2000-10-01</publish_date>
            " <description>An in-depth look at creating \
                        "applications with XML.</description>
            " </book>
            "</catalog>
            ""
        print(xml)

        assert( xml == _"<?xml version="1.0"?>
            "<catalog>
            " <book id="bk101" empty="">
            " <author>\(author)</author>
            " <title>XML Developer's Guide</title>
            " <genre>Computer</genre>
            " <price>44.95</price>
            " <publish_date>2000-10-01</publish_date>
            " <description>An in-depth look at creating applications with XML.</description>
            " </book>
            "</catalog>
            ""_ )

        try! NSRegularExpression(pattern: e"<([a-zA-Z][\w]*)", options: )
            .enumerateMatches(in: xml, options: , range: NSMakeRange(0, xml.utf16.count)) {
                (result, flags, stop) in
                print((xml as NSString).substring( with:result!.range(at: 1)))
        }

I’d not create a lexStringMultilineLiteral() function just yet as the changes are still minor as you
can see from the PR and due to the fact you can’t determine if a string is multiline until you
are half way through it. Excuse the “bottom up" approach but the reasoning is it would be no
accident that if the lexer and any changes to it are minimal, it will be easy to document and use.

John

On 1 May 2016, at 13:04, L Mihalkovic <laurent.mihalkovic@gmail.com <mailto:laurent.mihalkovic@gmail.com>> wrote:

[couple minutes read]

I read with great attention this thread, trying to see it from the implementation viewpoint (I know that the compiler structure should not drive the language features). I also revisited the how-to-contribute notes as well as the dev-process description. One of the ideas that stood out in my mind was that when looking at an implementation, enablement changes should be separated from the bulk of the feature, such that reviews can be easier.

So I tried to elevate this to the rank of a hidden-mandatory-requirement for anything related to this feature. It lead me to a staged approach to this feature that would allow a lot of things to be done, OVER TIME.

When distilling this feature to the smallest part enabler that would have to be added to the compiler I came to the following short list

add a string_multiline_token to the lexer
I realize that the current lexer can be tweaked to work (as per John’s PR), but IMO adding a dedicated "hole" in the parsing code is what will give something working today (no difference with current compiler behavior) while allowing all future changes to be cleanly isolated from anything around
if one accepts the idea of a hole created by the token, then it stands to reason to have delimiters around it. I looking at the structure of the grammar, I came to the conclusion that _” and “_ where an easy, unambiguous choice (I believe “”” and “”” looked like an equally easy an unambiguous choice)
the next choice should be the creation of a lexStringMultilineLiteral() and lexMultilineCharacter() method in the Lexer. Again… bare with me, I do believe it is relevant to what everyone wants this feature to be… The latter method should contain only extensions specific to multiline literals delegating common use cases to lexCharacter()

The main point of following this route (or any equivalent) is that
it represents a very clear commitment to multiline string literals
it ensures that there is no strong commitment to feature details, while allowing many future scenarios
it will remain backward compatible with enhancements to the current string literal syntax (translation?)
external contributors will be able to prototype while making sure we stay within strict boundaries for integration with the compiler

The next equally small step would be to describe the required minimal changes to Parser, a step I do not want to take now if the compiler experts view no merit at all to the proposed staged approach.

A thought experiment pushing further down this path, shows how the following would be equally possible language features (with roughly equivalent implementation cost):

let whyOwhy = “”"\
    !! Can't understand what improvements it truly delivers
    !! It basically removes a handful of characters
    !! It works today
    !! But I don't see it as a likable foundations for adding in future enhancements
    !!\
    !! I don't envy the people who will have to support it outside of xcode
    !! Or even in xcode (considering how it currently struggles with indents/formatting
    !! As for elegance, beauty is in the eye of the beholder, they say.
“”"
var json1 = _"[json]\
    !!{
    !! "file" : "\(wishIhadPlaceholders)_000.md"
    !! "desc" : "and why are all examples in xml, i thought it died a while ago ;-)"
    !! "rational" : [
    !! "Here we go again"
    !! "How will xcode help make these workable"
    !! ]
    !!}
“_
var json2 = _"[json]\
{
  "file" : "\(wishIhadPlaceholders)_000.md"
  "desc" : "and why are all examples in xml, i thought it died a while ago ;-)"
  "rational" : [
          "Here we go again"
          "How will xcode help make these workable"
       ]
}
“_

[_"] --> start string
[_"\] --> start line + ignore spaces until eol (basically swallow \r\n)
[!!\] --> ignore everything until eol... basically the gap does not exits
["_] --> terminate string
[_"[TYPEID]\] --> start string knowing that it a verifyer or a formatter (or a chain of) understanding TYPEID can syntax check or format or or or

IMO splitting these expression from the current lexing/parsing has another long term benefits when coupled with the aforementioned idea of contents tagging:
allow external dedicated formatter to be created in any editor supporting swift
allow external validators (including in the form of compiler plugins)
open a door for an equivalent to the scala's macros for contents marked as [swift]

Once again I fully appreciate that implementation should not drive language design, but considering the flurry of great ideas, I thought it might in this instance be useful to identify a minimal, noncommittal, direction common to many scenarios, such that a step can be taken that will neither favor nor prohibit any of the proposals, but simply enable them all.

Thank you for your patience
Regards

PS: I am working on a rudimentary implementation that I hope could help people test all the ideas floating in this list.

On Apr 26, 2016, at 8:04 AM, Chris Lattner via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Apr 25, 2016, at 5:22 PM, Brent Royal-Gordon <brent@architechies.com <mailto:brent@architechies.com>> wrote:

3. It might be useful to make multiline `"` strings trim trailing whitespace and comments like Perl's `/x` regex modifier does.

If you have modifier characters already, it is easy to build a small zoo full of these useful beasts.

Modifiers are definitely a workable alternative, and can be quite flexible, particularly if a future macro system can let you create new modifiers.

Right. I consider modifiers to be highly precedented in other languages, and therefore proven to work. If we go this way, I greatly prefer prefix to postfix modifiers.

* Alternative delimiters: If a string literal starts with three, or five, or seven, or etc. quotes, that is the delimiter, and fewer quotes than that in a row are simply literal quote marks. Four, six, etc. quotes is a quote mark abutting the end of the literal.

  let xml: String = """<?xml version="1.0"?>
        """<catalog>
        """\t<book id="bk101" empty="">
        """\t\t<author>\(author)</author>
        """\t</book>
        """</catalog>"""

You can't use this syntax to express an empty string, or a string consisting entirely of quote marks, but `""` handles empty strings adequately, and escaping can help with quote marks. (An alternative would be to remove the abutting rule and permit `""""""` to mean "empty string", but abutting quotes seem more useful than long-delimiter empty strings.)

I agree that there is a need to support alternative delimiters, but subjectively, I find this to be pretty ugly. It is also a really unfortunate degenerate case for “I just want a large blob of XML” because you’d end up using “"” almost all the time, and you have to use it on every line.

On the other hand, the `"""` does form a much larger, more obvious continuation indicator. It is *extremely* obvious that the above line is not Swift code, but something else embedded in it. It's also extremely obvious what its extent is: when you stop seeing `"""`, you're back to normal Swift code.

Right, but it is also heavy weight and ugly. In your previous email you said about the single quote approach: "The quotation marks on the left end up forming a column that marks the lines as special”, so I don’t see a need for a triple quote syntax to solve this specific problem.

I *really* don't like the idea of our only alternatives being "one double-quote mark with backslashing" or "use an entire heredoc". Heredocs have their place, but they are a *very* heavyweight quoting mechanism, and relatively short strings with many double-quotes are pretty common. (Consider, for instance, strings containing unparsed JSON.) I think we need *some* alternative to double-quotes, either single-quotes (with the same semantics, just as an alternative) or this kind of quote-stacking.

I agree that this is a real problem that would be great to solve.

If I step back and look at the string literal space we’re discussing, I feel like there are three options:

1) single and simple multiline strings, using “
2) your triple quote sort of string, specifically tuned to avoid having to escape “ when it occurs once or twice in sequence.
3) heredoc, which is a very general (but also very heavy weight) solution to quoting problems.

I’m trying to eliminate the middle one, so we only have to have "two things”. Here are some alternative ways to solve the problem, which might have less of an impact on the language:

A) Introduce single quoted string literals to avoid double quote problems specifically, e.g.: ‘look “here” I say!’. This is another form of #2 which is less ugly. It also doesn’t help you if you have both “ and ‘ in your string.

B) Introduce a modifier character that requires a more complex closing sequence to close off the string, see C++ raw string literals for prior art on this approach. Perhaps something like:

   Rxxx”look “ here “ I can use quotes “xxx

That said, I still prefer C) "ignore this issue for now”. In other words, I wouldn’t want to block progress on improving the string literal situation overall on this issue, because anything we do here is an further extension to a proposal that doesn’t solve this problem.

For cases like this, I think it would be reasonable to have a “heredoc” like scheme, which does not allow leading indentation, and does work with all the same modifier characters above. I do not have a preference on a particular syntax, and haven’t given it any thought, but this would allow you to do things like:

  let str = <<EOF
<?xml version="1.0"?>
<catalog>
\t<book id="bk101" empty="">
\t\t<author>\(author)</author>
\t</book>
</catalog>
EOF

for example. You could then turn off escaping and other knobs using the modifier character (somehow, it would have to be incorporated into the syntax of course).

There are two questions and a suggestion I have whenever heredoc syntax comes up.

Q1: Does the heredoc begin immediately, at the next line, or at the next valid place for a statement to start? Heredocs traditionally take the second approach.

Q2: Do you permit heredocs to stack—that is, for a single line to specify multiple heredocs?

S: During the Perl 6 redesign, they decided to use the delimiter's indentation to determine the base indentation for the heredoc:

  func x() -> String {
    return <<EOF
    <?xml version="1.0"?>
    <catalog>
    \t<book id="bk101" empty="">
    \t\t<author>\(author)</author>
    \t</book>
    </catalog>
    EOF
  }

Does that seem like a good approach?

I think that either approach could work, that you have a lot more experience on these topics than I do, and I would expect a vigorous community debate about these topics. :-)

That said, if you look at what we’re discussing:

1. “Continuation" string literals, to allow a multi-line string literal. You and I appear to completely agree about this.
2. Heredoc: You and I seem to agree that they are a good “fully general” solution to have, but there are the details you outline above to iron out.
3. Modifier characters: I’m in favor, but I don’t know where you stand. There is also still much to iron out here (such as the specific characters).
4. A way to avoid having to escape “ in a non-heredoc literal. I’m still unconvinced, and think that any solution to this problem will be orthogonal to the problems solved by 1-3 (and therefore can be added after getting experience with the other parts).

If you agree that these are all orthogonal pieces, then treat them as such: I’d suggest that you provide a proposal that just tackles the continuation string literals. This seems simple, and possible to get in for Swift 3. After that, we can discuss heredoc and modifiers (if you think they’re a good solution) on their own threads. If those turn out to be uncontroversial, then perhaps they can get in too.

On the heredoc aspects specifically, unless others chime in with strong opinions about the topics you brought up, I’d suggest that you craft a proposal for adding them with your preferred solution to these. You can mention the other answers (along with their tradeoffs and rationale for why you picked whatever you think is right) in the proposal, and we can help the community hash it out.

What do you think?

-Chris

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

Hi Brent,

What I mean is a document like the error handling rationale. Since there are so many potential solutions to this problem.

And ah right! You were the one who responded and proposed an implementation.

Thanks,

Tyler

···

On Apr 27, 2016, at 2:19 PM, Tyler Cloutier via swift-evolution <swift-evolution@swift.org> wrote:

Hi Brent,

This is essentially the same solution I proposed way back in December: [swift-evolution] multi-line string literals

I still have the same reservations about copying and pasting. Copying a string into your code is going to require adding a continuation quote on every line. If the string being added has quotes itself, the process of adding continuation quotes is going to make the syntax highlighter go bonkers while they are being inserted.

Should we not have a master document that considers the pros and cons of many different solutions? I started writing one such treatise a few weeks ago, but I haven’t been able to finish it yet. Just being able to see all of the potential implementations compared in one place but provide some insight. I imagine that this a feature that won’t change once it’s implemented, so it’s important to get it right.

Tyler

On Apr 27, 2016, at 1:58 PM, Chris Lattner via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Apr 27, 2016, at 1:52 AM, Brent Royal-Gordon <brent@architechies.com <mailto:brent@architechies.com>> wrote:

If you agree that these are all orthogonal pieces, then treat them as such: I’d suggest that you provide a proposal that just tackles the continuation string literals. This seems simple, and possible to get in for Swift 3.

I've gone ahead and drafted this proposal, with some small extensions and adjustments. See the "Draft Notes" section for details of what I've changed and what concerns I have.

Awesome. Some specific suggestions below, but feel free to iterate in a pull request if you prefer that.

<https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#introduction&gt;Introduction

In Swift 2.2, the only means to insert a newline into a string literal is the \n escape. String literals specified in this way are generally ugly and unreadable. We propose a multiline string feature inspired by English punctuation which is a straightforward extension of our existing string literals.

Swift-evolution thread: multi-line string literals. <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160418/015500.html&gt;I would suggest - right up front - pointing out that “heredoc” style syntaxes are another potential solution to this problem, but that they are heavier weight (and other tradeoffs). This proposal doesn’t attempt to address there heredoc usecase, but it also doesn’t preclude adding it. It is also mentioning up front that this is part of multi-part proposal to make string literals nicer, and point to the “possible future directions” section at the end.
<https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#draft-notes&gt;Draft Notes

This draft differs from the prototypes being thrown around on the list in that it specifies that comments should be treated as whitespace, and that whitespace-only lines in the middle of a multiline string should be ignored. I'm not sure if this is feasible from a parsing standpoint, and I'd like feedback from implementers on this point.

White space seems “implementable”, but I’m not sure that it is good. Visually, it would break up the string literal and make it less obviously a unit.

Comments on the same line as a string chunk should *not* be split out IMO, in:

   let s = “fooo // hello world
              “ nice to know you”

the “hello world” text should be included in the literal. I suppose it would be possible to allow comments on whitespace lines, but I don’t see a reason to do that. I’d suggest starting simple, since that could always be added down the road if there was great demand.

This draft also specifies diagnostics which should be included. Feedback on whether these are good choices would be welcome.

I’d just say that these are suggested diagnostics that can be word smithed later.

I am considering allowing you to put a backslash before the newline to indicate it should not be included in the literal. In other words, this code:

print("foo\
"bar")
Would print "foobar". However, I think this should probably be proposed separately, because there may be a better way to do it.

I don’t see a reason to do that. Why would this be helpful?

Benefits of continuation quotes

It would be simpler to not require continuation quotes,

I’d suggest being explicit here:

"It would be simpler to not require continuation quotes at the start of subsequent lines, "

Rules 1 and 2 should treat comments as though they are whitespace; this allows you to comment out individual lines in a multiline string literal. (However, commenting out the last line of the string literal will still make it unterminated, so you don't have a completely free hand in commenting.)

As I mentioned above, I’d suggest keeping the proposal minimal - that makes it more likely to be accepted since you’re removing something that the discussion could rathole on.

Impact on existing code

Failing to close a string literal before the end of the line is currently a syntax error, so no valid Swift code should be affected by this change.

I would add a “Potential Future Directions” section here, mention modifier characters, here doc, etc. That will help explain how this proposal fits into your broader plan, and address the question of “ok, your XML example looks a little better, but what’s with all the escaping?!??” :-)

This has several advantages:

It is simpler.

It is less offensive to programmers' sensibilities (since there are no unmatched " characters).

It does not require that you edit the string literal to insert a continuation quote in each line.

Balanced against the advantages, however, is the loss of the improved diagnostics, code formatting, and visual affordances mentioned in the "Benefits of continuation quotes" section above.

Just a writing observation, but by bulleting the advantages (and not bulleting the disadvantages) you’re making it look visually like the advantages are stronger or more important than the disadvantages.

<https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#use-a-different-delimiter-for-multiline-strings&gt;Use a different delimiter for multiline strings

The initial suggestion was that multiline strings should use a different delimiter, """, at the beginning and end of the string, with no continuation characters between.

Personally, I think that “”” could be the compelling heredoc designator we will also need. :-) It would certainly fit elegantly with modifier characters, the same way that “” does.

-Chris

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto: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

Regards
(From mobile)

Can this concept be dealt with my allowing a string file to be imported and assigned to a string constant? All happening at compile time and using #include type concept from C? It would tackle at least a reasonable subset of the issue in a way that I think works better for source control, etc.

let xml = @stringfile("Foo/Bar/baz.xml");

If memory serves me, this is not unlike what D does, with the added restriction of binding the contents to a single variable.

···

On Apr 27, 2016, at 6:51 PM, Shawn Erickson via swift-evolution <swift-evolution@swift.org> wrote:

On Wed, Apr 27, 2016 at 9:35 AM John Siracusa via swift-evolution <swift-evolution@swift.org> wrote:

On Wed, Apr 27, 2016 at 9:08 AM, Vladimir.S via swift-evolution <swift-evolution@swift.org> wrote:
I expect to be able to have multiline text exactly *"as-is"* in my source file. No escaping, no interpolation, etc. I believe this should be a target of the proposal.

I also see this as one of the most important goals of any multi-line string-handling proposal. The "no escapes required" syntax doesn't have to be the only way to handle multi-line strings, but it should be one of the available ways.

-John

P.S. - Secondarily (and broader than just multi-line strings) I think there should also be a way to avoid backslash-itis in strings of all kinds by providing some flexibility in string delimiters. But that's for another thread…

Otherwise, I reject to see any reason to introduce anything new at this area - we already can concatenate strings and place them on next line and escape special characters.

In your proposal, you have to escape characters in your text, you need to carefully modify the copy-pasted text to be allowed as correct multi-line string. Also, what if I need to have spaces *at the end of string* ? Editor can just trimmed them, and we can't clearly see them.

Personally I need to be able to have this(in some way) in my code:
(note this "\tuttorial" and "\(edition" - this is just text, I want to have inside my xml)

let xml = ... // some marker to start the multi-line str
<?xml version="1.0"?>
<catalog>
    <book id="myid" empty="">
        <author>myAuthor</author>
        <title>myTitle \tutorial 1\(edition 2)</title>
    </book>
</catalog>
... // some marker here to stop multi-line str

It seems like we need some markers for end-of-the-line to be able to keep spaces/tabs in the end of line.

What about something like this. Two suported variants : first when we need to keep spaces in the end of line, and second when we don't need spaced(will be trimmed by parser)

#1 (parser should just take the text between first and last quote *as-is*)

let xml = "\
"<?xml version="1.0"?> " // yes, *I need* these spaces at the end
"<catalog>"
" <book id="myid" empty="">"
" <author>myAuthor</author>"
" <title>myTitle \tutorial 1\(edition 2)</title>"
" </book>"
"</catalog>"
"

#2 in this case we don't need any spaces/tabs in the end of lines(don't care):
(parser takes all that is after | as-is but trims any trailing spaces/tabs in lines to be clear in behaviour)

let xml = "\
><?xml version="1.0"?>
><catalog>
> <book id="myid" empty="">
> <author>myAuthor</author>
> <title>myTitle \tutorial 1\(edition 2)</title>
> </book>
></catalog>
"

Or these two could be combined in one(as-is between |..|) but I'm not sure:

let xml = "\
><?xml version="1.0"?> | // yes, I need these spaces
><catalog>| // we have to have closing symbol in this case in other lines
> <book id="myid" empty="">|
> <author>myAuthor</author>|
> <title>myTitle \tutorial 1\(edition 2)</title>|
> </book>|
></catalog>|
"

Gist: <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f&gt;

  Multiline string literals

  * Proposal: SE-NNNN
    <https://github.com/apple/swift-evolution/blob/master/proposals/NNNN-name.md&gt;
  * Author(s): Brent Royal-Gordon <https://github.com/brentdax&gt;
  * Status: First Draft
  * Review manager: TBD

    <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#introduction&gt;Introduction

In Swift 2.2, the only means to insert a newline into a string literal is
the |\n| escape. String literals specified in this way are generally ugly
and unreadable. We propose a multiline string feature inspired by English
punctuation which is a straightforward extension of our existing string
literals.

Swift-evolution thread: multi-line string literals.
<https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160418/015500.html&gt;

    <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#draft-notes&gt;Draft
    Notes

  *

    This draft differs from the prototypes being thrown around on the list
    in that it specifies that comments should be treated as whitespace, and
    that whitespace-only lines in the middle of a multiline string should
    be ignored. I'm not sure if this is feasible from a parsing standpoint,
    and I'd like feedback from implementers on this point.

  *

    This draft also specifies diagnostics which should be included.
    Feedback on whether these are good choices would be welcome.

  *

    I am considering allowing you to put a backslash before the newline to
    indicate it should /not/ be included in the literal. In other words,
    this code:

    print("foo\
    "bar")

    Would print |"foobar"|. However, I think this should probably be
    proposed separately, because there may be a better way to do it.

  *

    I've listed only myself as an author because I don't want to put anyone
    else's name to a document they haven't seen, but there are others who
    deserve to be listed (John Holdsworth at least). Let me know if you
    think you should be included.

    <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#motivation&gt;Motivation

As Swift begins to move into roles beyond app development, code which needs
to generate text becomes a more important use case. Consider, for instance,
generating even a small XML string:

let xml = "<?xml version=\"1.0\"?>\n<catalog>\n\t<book id=\"bk101\"
empty=\"\">\n\t\t<author>\(author)</author>\n\t</book>\n</catalog>"

The string is practically unreadable, its structure drowned in escapes and
run-together characters; it looks like little more than line noise. We can
improve its readability somewhat by concatenating separate strings for each
line and using real tabs instead of |\t| escapes:

let xml = "<?xml version=\"1.0\"?>\n" +
          "<catalog>\n" +
          " <book id=\"bk101\" empty=\"\">\n" +
          " <author>\(author)</author>\n" +
          " </book>\n" +
          "</catalog>"

However, this creates a more complex expression for the type checker, and
there's still far more punctuation than ought to be necessary. If the most
important goal of Swift is making code readable, this kind of code falls
far short of that goal.

    <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#proposed-solution&gt;Proposed
    solution

We propose that, when Swift is parsing a string literal, if it reaches the
end of the line without encountering an end quote, it should look at the
next line. If it sees a quote mark there (a "continuation quote"), the
string literal contains a newline and then continues on that line.
Otherwise, the string literal is unterminated and syntactically invalid.

Our sample above could thus be written as:

let xml = "<?xml version=\"1.0\"?>
"<catalog>
          " <book id=\"bk101\" empty=\"\">
" <author>\(author)</author>
          " </book>
"</catalog>"

(Note that GitHub is applying incorrect syntax highlighting to this code
sample, because it's applying Swift 2 rules.)

This format's unbalanced quotes might strike some programmers as strange,
but it attempts to mimic the way multiple lines are quoted in English
prose. As an English Stack Exchange answer illustrates
<punctuation - Why does the multi-paragraph quotation rule exist? - English Language & Usage Stack Exchange

    “That seems like an odd way to use punctuation,” Tom said. “What harm
    would there be in using quotation marks at the end of every paragraph?”

    “Oh, that’s not all that complicated,” J.R. answered. “If you closed
    quotes at the end of every paragraph, then you would need to reidentify
    the speaker with every subsequent paragraph.

    “Say a narrative was describing two or three people engaged in a
    lengthy conversation. If you closed the quotation marks in the previous
    paragraph, then a reader wouldn’t be able to easily tell if the
    previous speaker was extending his point, or if someone else in the
    room had picked up the conversation. By leaving the previous
    paragraph’s quote unclosed, the reader knows that the previous speaker
    is still the one talking.”

    “Oh, that makes sense. Thanks!”

Similarly, omitting the ending quotation mark tells the code's reader (and
compiler) that the literal continues on the next line, while including the
continuation quote reminds the reader (and compiler) that this line is part
of a string literal.

      <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#benefits-of-continuation-quotes&gt;Benefits
      of continuation quotes

It would be simpler to not require continuation quotes, so why are they
required by this proposal? There are three reasons:

1.

    *They help the compiler pinpoint errors in string literal
    delimiting.* If continuation quotes were not required, then a missing
    end quote would be interpreted as a multiline string literal. This
    string literal would continue until the compiler encountered either
    another quote mark—perhaps at the site of another string literal or in
    a comment—or the end of the file. In either case, the compiler could at
    best only indicate the start of the runaway string literal; in
    pathological cases (for instance, if the next string literal
    was |"+"|), it might not even be able to do that properly.

    With continuation quotes required, if you forget to include an end
    quote, the compiler can tell that you did not intend to create a
    multiline string and flag the line that actually has the problem. It
    can also provide immediately actionable fix-it assistance. The fact
    that there is a redundant indication on each line of the programmer's
    intent to include that line in a multiline quote allows the compiler to
    guess the meaning of the code.

2.

    *They separate indentation from the string's contents.* Without
    continuation quotes, there would be no obvious indication of whether
    whitespace at the start of the line was intended to indent the string
    literal so it matched the surrounding code, or whether that whitespace
    was actually meant to be included in the resulting string. Multiline
    string literals would either have to put subsequent lines against the
    left margin, or apply error-prone heuristics to try to guess which
    whitespace was indentation and which was string literal content.

3.

    *They improve the ability to quickly recognize the literal.* The |"| on
    each line serves as an immediately obvious indication that the line is
    part of a string literal, not code, and the row of |"| characters in a
    well-formatted file allows you to quickly scan up and down the file to
    see the extent of the literal.

    <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#detailed-design&gt;Detailed
    design

When Swift is parsing a string literal and reaches the end of a line
without finding a closing quote, it examines the next line, applying the
following rules:

1.

    If the next line is all whitespace, it is ignored; Swift moves on to
    the line afterward, applying these rules again.

2.

    If the next line begins with whitespace followed by a continuation
    quote, then the string literal contains a newline followed by the
    contents of the string literal starting on that line. (This line may
    itself have no closing quote, in which case the same rules apply to the
    line which follows.)

3.

    If the next line contains anything else, Swift raises a syntax error
    for an unterminated string literal. This syntax error should offer two
    fix-its: one to close the string literal at the end of the current
    line, and one to include the next line in the string literal by
    inserting a continuation quote.

Rules 1 and 2 should treat comments as though they are whitespace; this
allows you to comment out individual lines in a multiline string literal.
(However, commenting out the last line of the string literal will still
make it unterminated, so you don't have a completely free hand in commenting.)

    <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#impact-on-existing-code&gt;Impact
    on existing code

Failing to close a string literal before the end of the line is currently a
syntax error, so no valid Swift code should be affected by this change.

    <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#alternatives-considered&gt;Alternatives
    considered

      <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#requiring-no-continuation-character&gt;Requiring
      no continuation character

The main alternative is to not require a continuation quote, and simply
extend the string literal from the starting quote to the ending quote,
including all newlines between them. For example:

let xml = "<?xml version=\"1.0\"?>
<catalog>
<book id=\"bk101\" empty=\"\">
<author>\(author)</author>
</book>
</catalog>"

This has several advantages:

1.

    It is simpler.

2.

    It is less offensive to programmers' sensibilities (since there are no
    unmatched |"| characters).

3.

    It does not require that you edit the string literal to insert a
    continuation quote in each line.

Balanced against the advantages, however, is the loss of the improved
diagnostics, code formatting, and visual affordances mentioned in the
"Benefits of continuation quotes" section above.

In practice, we believe that editor support (such as "Paste as String
Literal" or "Convert to String Literal" commands) can make adding
continuation quotes less burdensome, while also providing other
conveniences like automatic escaping. We believe the other two factors are
outweighed by the benefits of continuation quotes.

      <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#use-a-different-delimiter-for-multiline-strings&gt;Use

      a different delimiter for multiline strings

The initial suggestion was that multiline strings should use a different
delimiter, |"""|, at the beginning and end of the string, with no
continuation characters between. This solution was rejected because it has
the same issues as the "no continuation character" solution, and because it
was mixing two orthogonal issues (multiline strings and alternate delimiters).

Another suggestion was to support a heredoc syntax, which would allow you
to specify a placeholder string literal on one line whose content begins on
the next line, running until some arbitrary delimiter. For instance, if
Swift adopted Perl 5's syntax, it might support code like:

connection.sendString(<<"END")
<?xml version="1.0"?>
<catalog>
    <book id="bk101" empty="">
        <author>\(author)</author>
    </book>
</catalog>
END

In addition to the issues with the |"""| syntax, heredocs are complicated
both to explain and to parse, and are not a natural extension of Swift's
current string syntax.

Both of these suggestions address interesting issues with string literals,
solving compelling use cases. They're just not that good at fixing the
specific issue at hand. We might consider them in the future to address
those problems to which they are better suited.

      <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#fixing-other-string-literal-readability-issues&gt;Fixing
      other string literal readability issues

This proposal is narrowly aimed at multiline strings. It intentionally
doesn't tackle several other problems with string literals:

  *

    Reducing the amount of double-backslashing needed when working with
    regular expression libraries, Windows paths, source code generation,
    and other tasks where backslashes are part of the data.

  *

    Alternate delimiters or other strategies for writing strings
    with |"| characters in them.

  *

    String literals consisting of very long pieces of text which are best
    represented completely verbatim.

These are likely to be subjects of future proposals, though not necessarily
during Swift 3.

This proposal also does not attempt to address regular expression literals.
The members of the core team who are interested in regular expression
support have ambitions for that feature which put it out of scope for Swift 3.

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

_______________________________________________
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

Should we not have a master document that considers the pros and cons of many different solutions? I started writing one such treatise a few weeks ago, but I haven’t been able to finish it yet. Just being able to see all of the potential implementations compared in one place but provide some insight. I imagine that this a feature that won’t change once it’s implemented, so it’s important to get it right.

That might be a useful document to have, but I worry that we'll end up seeing the string feature proposals signed in triplicate, sent in, sent back, queried, lost, found, subjected to public inquiry, lost again, and finally buried in soft peat for three months and recycled as firelighters, all to end up in with basically the same proposals but with slightly different keywords. Not every decision needs that level of explicit, deep documentation. Some things you can think about, experiment with, discuss, and do.

···

--
Brent Royal-Gordon
Architechies

is it just me who would prefer a multiline string literal to not require a \backslash before each "double quote"?

Did you ever really use multiline string literals before? I did, and it's mostly for quick hacks where I wrote a script or tried something out quickly. And maybe I needed to put an XML snippet into a unit test case to see if my parser correctly parses or correctly rejects the snippet. The current proposal doesn't help this use case in any way. I cannot see which use case inspires multiline string literals which require double quotes to be escaped... I wouldn't use them if they were available. I'd become an Android developer instead ;)

-Michael

···

Am 28.04.2016 um 23:56 schrieb Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org>:

Awesome. Some specific suggestions below, but feel free to iterate in a pull request if you prefer that.

I've adopted these suggestions in some form, though I also ended up rewriting the explanation of why the feature was designed as it is and fusing it with material from "Alternatives considered".

(Still not sure who I should list as a co-author. I'm currently thinking John, Tyler, and maybe Chris? Who's supposed to go there?)

Multiline string literals

  • Proposal: SE-NNNN
  • Author(s): Brent Royal-Gordon
  • Status: Second Draft
  • Review manager: TBD
Introduction

In Swift 2.2, the only means to insert a newline into a string literal is the \n escape. String literals specified in this way are generally ugly and unreadable. We propose a multiline string feature inspired by English punctuation which is a straightforward extension of our existing string literals.

This proposal is one step in a larger plan to improve how string literals address various challenging use cases. It is not meant to solve all problems with escaping, nor to serve all use cases involving very long string literals. See the "Future directions for string literals in general" section for a sketch of the problems we ultimately want to address and some ideas of how we might do so.

Swift-evolution threads: multi-line string literals. (April), multi-line string literals (December)

Draft Notes

  • Removes the comment feature, which was felt to be an unnecessary complication. This and the backslash feature have been listed as future directions.

  • Loosens the specification of diagnostics, suggesting instead of requiring fix-its.

  • Splits a "Rationale" section out of the "Proposed solution" section.

  • Adds extensive discussion of other features which wold combine with this one.

  • I've listed only myself as an author because I don't want to put anyone else's name to a document they haven't seen, but there are others who deserve to be listed (John Holdsworth at least). Let me know if you think you should be included.

Motivation

As Swift begins to move into roles beyond app development, code which needs to generate text becomes a more important use case. Consider, for instance, generating even a small XML string:

let xml = "<?xml version=\"1.0\"?>\n<catalog>\n\t<book id=\"bk101\" empty=\"\">\n\t\t<author>\(author)</author>\n\t</book>\n</catalog>"
The string is practically unreadable, its structure drowned in escapes and run-together lines; it looks like little more than line noise. We can improve its readability somewhat by concatenating separate strings for each line and using real tabs instead of \t escapes:

let xml = "<?xml version=\"1.0\"?>\n" +

"<catalog>\n" +

" <book id=\"bk101\" empty=\"\">\n" +

" <author>\(author)</author>\n" +

" </book>\n" +

"</catalog>"
However, this creates a more complex expression for the type checker, and there's still far more punctuation than ought to be necessary. If the most important goal of Swift is making code readable, this kind of code falls far short of that goal.

Proposed solution

We propose that, when Swift is parsing a string literal, if it reaches the end of the line without encountering an end quote, it should look at the next line. If it sees a quote at the beginning (a "continuation quote"), the string literal contains a newline and then continues on that line. Otherwise, the string literal is unterminated and syntactically invalid.

Our sample above could thus be written as:

let xml = "<?xml version=\"1.0\"?>
          "<catalog>
          " <book id=\"bk101\" empty=\"\">
          " <author>\(author)</author>
          " </book>
          "</catalog>"

If the second or subsequent lines had not begun with a quotation mark, or the trailing quotation mark after the </catalog>tag had not been included, Swift would have emitted an error.

Rationale

This design is rather unusual, and it's worth pausing a moment to explain why it has been chosen.

The traditional design for this feature, seen in languages like Perl and Python, simply places one delimiter at the beginning of the literal and another at the end. Individual lines in the literal are not marked in any way.

We think continuation quotes offer several important advantages over the traditional design:

  • They help the compiler pinpoint errors in string literal delimiting. Traditional multiline strings have a serious weakness: if you forget the closing quote, the compiler has no idea where you wanted the literal to end. It simply continues on until the compiler encounters another quote (or the end of the file). If you're lucky, the text after that quote is not valid code, and the resulting error will at least point you to the next string literal in the file. If you're unlucky, you'll get a seemingly unrelated error several literals later, an unbalanced brace error at the end of the file, or perhaps even code that compiles but does something totally wrong.

(This is not a minor concern. Many popular languages, including C and Swift 2, specifically reject newlines in string literals to prevent this from happening.)

Continuation quotes provide the compiler with redundant information about your intent. If you forget a closing quote, the continuation quotes give the compiler a very good idea of where you meant to put it. The compiler can point you to (or at least very near) the end of the literal, where you want to insert the quote, rather than showing you the beginning of the literal or even some unrelated error later in the file that was caused by the missing quote.

  • Temporarily unclosed literals don't make editors go haywire. The syntax highlighter has the same trouble parsing half-written, unclosed traditional quotes that the compiler does: It can't tell where the literal is supposed to end and the code should begin. It must either apply heuristics to try to guess where the literal ends, or incorrectly color everything between the opening quote and the next closing quote as a string literal. This can cause the file's coloring to alternate distractingly between "string literal" and "running code".

Continuation quotes give the syntax highlighter enough context to guess at the correct coloration, even when the string isn't complete yet. Lines with a continuation quote are literals; lines without are code. At worst, the syntax highlighter might incorrectly color a few characters at the end of a line, rather than the remainder of the file.

  • They separate indentation from the string's contents. Traditional multiline strings usually include all of the content between the start and end delimiters, including leading whitespace. This means that it's usually impossible to indent a multiline string, so including one breaks up the flow of the surrounding code, making it less readable. Some languages apply heuristics or mode switches to try to remove indentation, but like all heuristics, these are mistake-prone and murky.

Continuation quotes neatly avoid this problem. Whitespace before the continuation quote is indentation used to format the source code; whitespace after the continuation quote is part of the string literal. The interpretation of the code is perfectly clear to both compiler and programmer.

  • They improve the ability to quickly recognize the literal. Traditional multiline strings don't provide much visual help. To find the end, you must visually scan until you find the matching delimiter, which may be only one or a few characters long. When looking at a random line of source, it can be hard to tell at a glance whether it's code or literal. Syntax highlighting can help with these issues, but it's often unreliable, especially with advanced, idiosyncratic string literal features like multiline strings.

Continuation quotes solve these problems. To find the end of the literal, just scan down the column of continuation characters until they end. To figure out if a given line of source is part of a literal, just see if it starts with a quote mark. The meaning of the source becomes obvious at a glance.

Nevertheless, the traditional design does has a few advantages:

  • It is simpler. Although continuation quotes are more complex, we believe that the advantages listed above pay for that complexity.

  • There is no need to edit the intervening lines to add continuation quotes. While the additional effort required to insert continuation quotes is an important downside, we believe that tool support, including both compiler fix-its and perhaps editor support for commands like "Paste as String Literal", can address this issue. In some editors, new features aren't even necessary; TextMate, for instance, lets you insert a character on several lines simultaneously. And new tool features could also address other issues like escaping embedded quotes.

  • Naïve syntax highlighters may have trouble understanding this syntax. This is true, but naïve syntax highlighters generally have terrible trouble with advanced string literal constructs; some struggle with even basic ones. While there are some designs (like Python's """ strings) which trick some syntax highlighters into working some of the time with some contents, we don't think this occasional, accidental compatibility is a big enough gain to justify changing the design.

  • It looks funny—quotes should always be in matched pairs. We aren't aware of another programming language which uses unbalanced quotes in string literals, but there is one very important precedent for this kind of formatting: natural languages. English, for instance, uses a very similar format for quoting multiple lines of dialog by the same speaker. As an English Stack Exchange answer illustrates:

“That seems like an odd way to use punctuation,” Tom said. “What harm would there be in using quotation marks at the end of every paragraph?”

“Oh, that’s not all that complicated,” J.R. answered. “If you closed quotes at the end of every paragraph, then you would need to reidentify the speaker with every subsequent paragraph.

“Say a narrative was describing two or three people engaged in a lengthy conversation. If you closed the quotation marks in the previous paragraph, then a reader wouldn’t be able to easily tell if the previous speaker was extending his point, or if someone else in the room had picked up the conversation. By leaving the previous paragraph’s quote unclosed, the reader knows that the previous speaker is still the one talking.”

“Oh, that makes sense. Thanks!”
In English, omitting the ending quotation mark tells the text's reader that the quote continues on the next line, while including a quotation mark at the beginning of the next line reminds the reader that they're in the middle of a quote.

Similarly, in this proposal, omitting the ending quotation mark tells the code's reader (and compiler) that the string literal continues on the next line, while including a quotation mark at the beginning of the next line reminds the reader (and compiler) that they're in the middle of a string literal.

On balance, we think continuation quotes are the best design for this problem.

Detailed design

When Swift is parsing a string literal and reaches the end of a line without finding a closing quote, it examines the next line, applying the following rules:

  • If the next line begins with whitespace followed by a continuation quote, then the string literal contains a newline followed by the contents of the string literal starting on that line. (This line may itself have no closing quote, in which case the same rules apply to the line which follows.)

  • If the next line contains anything else, Swift raises a syntax error for an unterminated string literal.

The exact error messages and diagnostics provided are left to the implementers to determine, but we believe it should be possible to provide two fix-its which will help users learn the syntax and correct string literal mistakes:

  • Insert " at the end of the current line to terminate the quote.

  • Insert " at the beginning of the next line (with some indentation heuristics) to continue the quote on the next line.

Impact on existing code

Failing to close a string literal before the end of the line is currently a syntax error, so no valid Swift code should be affected by this change.

Future directions for multiline string literals

  • We could permit comments before encountering a continuation quote to be counted as whitespace, and permit empty lines in the middle of string literals. This would allow you to comment out whole lines in the literal.

  • We could allow you to put a trailing backslash on a line to indicate that the newline isn't "real" and should be omitted from the literal's contents.

Future directions for string literals in general

There are other issues with Swift's string handling which this proposal intentionally does not address:

  • Reducing the amount of double-backslashing needed when working with regular expression libraries, Windows paths, source code generation, and other tasks where backslashes are part of the data.

  • Alternate delimiters or other strategies for writing strings with " characters in them.

  • Accommodating code formatting concerns like hard wrapping and commenting.

  • String literals consisting of very long pieces of text which are best represented completely verbatim, with minimal alteration.

This section briefly outlines some future proposals which might address these issues. Combined, we believe they would address most of the string literal use cases which Swift is currently not very good at.

Please note that these are simply sketches of hypothetical future designs; they may radically change before proposal, and some may never be proposed at all. Many, perhaps most, will not be proposed for Swift 3. We are sketching these designs not to propose and refine these features immediately, but merely to show how we think they might be solved in ways which complement this proposal.

String literal modifiers

A string literal modifier is a cluster of identifier characters which goes before a string literal and adjusts the way it is parsed. Modifers only alter the interpretation of the text in the literal, not the type of data it produces; for instance, there will never be something like the UTF-8/UTF-16/UTF-32 literal modifiers in C++. Uppercase characters enable a feature; lowercase characters disable a feature.

Modifiers can be attached to both single-line and multiline literals, and could also be attached to other literal syntaxes which might be introduced in the future. When used with multiline strings, only the starting quote needs to carry the modifiers, not the continuation quotes.

Modifiers are an extremely flexible feature which can be used for many proposes. Of the ideas listed below, we believe the e modifier is an urgent addition which should be included in Swift 3 if at all possible; the others are less urgent and most of them could be deferred, or at least added later if time allows.

  • Escape disabling: e"\\\" (string with three backslash characters)

  • Fine-grained escape disabling: i"\(foo)\n" (the string \(foo) followed by a newline); eI"\(foo)\n" (the contents of foo followed by the string \n), b"\w+\n" (the string \w+ followed by a newline)

  • Alternate delimiters: _ has no lowercase form, so it could be used to allow strings with internal quotes: _"print("Hello, world!")"_, __"print("Hello, world!")"__, etc.

  • Whitespace normalization: changes all runs of whitespace in the literal to single space characters; this would allow you to use multiline strings purely to improve code formatting.

alert.informativeText =
    W"\(appName) could not typeset the element “\(title)” because
     "it includes a link to an element that has been removed from this
     "book."

  • Localization:

alert.informativeText =
    LW"\(appName) could not typeset the element “\(title)” because
      "it includes a link to an element that has been removed from this
      "book."

  • Comments: Embedding comments in string literals might be useful for literals containing regular expressions or other code.

Eventually, user-specified string modifiers could be added to Swift, perhaps as part of a hygienic macro system. It might also become possible to change the default modifiers applied to literals in a particular file or scope.

Heredocs or other "verbatim string literal" features

Sometimes it really is best to just splat something else down in the middle of a file full of Swift source code. Maybe the file is essentially a template and the literals are a majority of the code's contents, or maybe you're writing a code generator and just want to get string data into it with minimal fuss, or maybe people unfamiliar with Swift need to be able to edit the literals. Whatever the reason, the normal string literal syntax is just too burdensome.

One approach to this problem is heredocs. A heredoc allows you to put a placeholder for a literal on one line; the contents of the literal begin on the next line, running up to some delimiter. It would be possible to put multiple placeholders in a single line, and to apply string modifiers to them.

In Swift, this might look like:

print(#to("---") + e#to("END"
))
It was a dark and stormy \(timeOfDay) when
---
the Swift core team invented the \(interpolation) syntax.
END

Another possible approach would be to support traditional multiline string literals bounded by a different delimiter, like """. This might look like:

print("""
It was a dark and stormy \(timeOfDay) when
""" + e"""
the Swift core team invented the \(interpolation) syntax.
""")
Although heredocs could make a good addition to Swift eventually, there are good reasons to defer them for now. Please see the "Alternatives considered" section for details.

First-class regular expressions

Members of the core team are interested in regular expressions, but they don't want to just build a literal that wraps PCRE or libicu; rather, they aim to integrate regexes into the pattern matching system and give them a deep, Perl 6-style rethink. This would be a major effort, far beyond the scope of Swift 3.

In the meantime, the e modifier and perhaps other string literal modifiers will make it easier to specify regular expressions in string literals for use with NSRegularExpression and other libraries accessible from Swift.

Alternatives considered

Requiring no continuation character

The main alternative is to not require a continuation quote, and simply extend the string literal from the starting quote to the ending quote, including all newlines between them. For example:

let xml = "<?xml version=\"1.0\"?>
<catalog>
    <book id=\"bk101\" empty=\"\">
        <author>\(author)</author>
    </book>
</catalog>"
This alternative is extensively discussed in the "Rationale" section above.

Skip multiline strings and just support heredocs

There are definitely cases where a heredoc would be a better solution, such as generated code or code which is mostly literals with a little Swift sprinkled around. On the other hand, there are also cases where multiline strings are better: short strings in code which is meant to be read. If a single feature can't handle them both well, there's no shame in supporting the two features separately.

It makes sense to support multiline strings first because:

  • They extend existing syntax instead of introducing new syntax.

  • They are much easier to parse; heredocs require some kind of mode in the parser which kicks in at the start of the next line, whereas multiline string literals can be handled in the lexer.

  • As discussed in "Rationale", they offer better diagnostics, code formatting, and visual scannability.

Use a different delimiter for multiline strings

The initial suggestion was that multiline strings should use a different delimiter, """, at the beginning and end of the string, with no continuation characters between. Like heredocs, this might be a good alternative for certain use cases, but it has the same basic flaws as the "no continuation character" solution.

--
Brent Royal-Gordon
Architechies

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

@Brent, I suggest to rename the proposal to be clear that it is not trying to solve the problem with char escaping i.e. with text *as-is*, that it is just removes the \n"+ from the end of the string. I think many can think of "as-is" text feature when starting to read your proposal or will ask questions like "why multi-line proposal does not include proposal for as-is multi-line", I feel like the title is too generic.

Regarding the proposal itself. I'm ready to support it (in case you'll add 'specification' of your multi-line feature in the title like "multi-line with support of escaping and interpolation", so we can then have another proposal like "multi-line without escaping, with text as-is")

One question: what about trailing spaces/tabs in the end of each line? IMO there should be one strict rule to prevent any hard-to-find bugs/errors : your feature must trim all trailing spaces, or should have an explicit marker when to do this or not.

···

On 29.04.2016 0:56, Brent Royal-Gordon via swift-evolution wrote:

Awesome. Some specific suggestions below, but feel free to iterate in a
pull request if you prefer that.

I've adopted these suggestions in some form, though I also ended up
rewriting the explanation of why the feature was designed as it is and
fusing it with material from "Alternatives considered".

(Still not sure who I should list as a co-author. I'm currently thinking
John, Tyler, and maybe Chris? Who's supposed to go there?)

  Multiline string literals

  * Proposal: SE-NNNN
    <https://github.com/apple/swift-evolution/blob/master/proposals/NNNN-name.md&gt;
  * Author(s): Brent Royal-Gordon <https://github.com/brentdax&gt;
  * Status: *Second Draft*
  * Review manager: TBD

    <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#introduction&gt;Introduction

In Swift 2.2, the only means to insert a newline into a string literal is
the |\n| escape. String literals specified in this way are generally ugly
and unreadable. We propose a multiline string feature inspired by English
punctuation which is a straightforward extension of our existing string
literals.

This proposal is one step in a larger plan to improve how string literals
address various challenging use cases. It is not meant to solve all
problems with escaping, nor to serve all use cases involving very long
string literals. See the "Future directions for string literals in general"
section for a sketch of the problems we ultimately want to address and some
ideas of how we might do so.

Swift-evolution threads: multi-line string literals. (April)
<https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160418/015500.html&gt;, multi-line
string literals (December)
<https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151214/002349.html&gt;

    <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#draft-notes&gt;Draft
    Notes

  *

    Removes the comment feature, which was felt to be an unnecessary
    complication. This and the backslash feature have been listed as future
    directions.

  *

    Loosens the specification of diagnostics, suggesting instead of
    requiring fix-its.

  *

    Splits a "Rationale" section out of the "Proposed solution" section.

  *

    Adds extensive discussion of other features which wold combine with
    this one.

  *

    I've listed only myself as an author because I don't want to put anyone
    else's name to a document they haven't seen, but there are others who
    deserve to be listed (John Holdsworth at least). Let me know if you
    think you should be included.

    <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#motivation&gt;Motivation

As Swift begins to move into roles beyond app development, code which needs
to generate text becomes a more important use case. Consider, for instance,
generating even a small XML string:

let xml = "<?xml version=\"1.0\"?>\n<catalog>\n\t<book id=\"bk101\"
empty=\"\">\n\t\t<author>\(author)</author>\n\t</book>\n</catalog>"

The string is practically unreadable, its structure drowned in escapes and
run-together lines; it looks like little more than line noise. We can
improve its readability somewhat by concatenating separate strings for each
line and using real tabs instead of |\t| escapes:

let xml = "<?xml version=\"1.0\"?>\n" +
          "<catalog>\n" +
          " <book id=\"bk101\" empty=\"\">\n" +
          " <author>\(author)</author>\n" +
          " </book>\n" +
          "</catalog>"

However, this creates a more complex expression for the type checker, and
there's still far more punctuation than ought to be necessary. If the most
important goal of Swift is making code readable, this kind of code falls
far short of that goal.

    <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#proposed-solution&gt;Proposed
    solution

We propose that, when Swift is parsing a string literal, if it reaches the
end of the line without encountering an end quote, it should look at the
next line. If it sees a quote at the beginning (a "continuation quote"),
the string literal contains a newline and then continues on that line.
Otherwise, the string literal is unterminated and syntactically invalid.

Our sample above could thus be written as:

>let xml = "<?xml version=\"1.0\"?> "<catalog> " <book id=\"bk101\"
empty=\"\"> " <author>\(author)</author> " </book> "</catalog>" |

If the second or subsequent lines had not begun with a quotation mark, or
the trailing quotation mark after the |</catalog>|tag had not been
included, Swift would have emitted an error.

      <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#rationale&gt;Rationale

This design is rather unusual, and it's worth pausing a moment to explain
why it has been chosen.

The traditional design for this feature, seen in languages like Perl and
Python, simply places one delimiter at the beginning of the literal and
another at the end. Individual lines in the literal are not marked in any way.

We think continuation quotes offer several important advantages over the
traditional design:

1.

    *They help the compiler pinpoint errors in string literal
    delimiting.* Traditional multiline strings have a serious weakness: if
    you forget the closing quote, the compiler has no idea where you wanted
    the literal to end. It simply continues on until the compiler
    encounters another quote (or the end of the file). If you're lucky, the
    text after that quote is not valid code, and the resulting error will
    at least point you to the next string literal in the file. If you're
    unlucky, you'll get a seemingly unrelated error several literals later,
    an unbalanced brace error at the end of the file, or perhaps even code
    that compiles but does something totally wrong.

    (This is not a minor concern. Many popular languages, including C and
    Swift 2, specifically reject newlines in string literals to prevent
    this from happening.)

    Continuation quotes provide the compiler with redundant information
    about your intent. If you forget a closing quote, the continuation
    quotes give the compiler a very good idea of where you meant to put it.
    The compiler can point you to (or at least very near) the /end/ of the
    literal, where you want to insert the quote, rather than showing you
    the /beginning/ of the literal or even some unrelated error later in
    the file that was caused by the missing quote.

2.

    *Temporarily unclosed literals don't make editors go haywire.* The
    syntax highlighter has the same trouble parsing half-written, unclosed
    traditional quotes that the compiler does: It can't tell where the
    literal is supposed to end and the code should begin. It must either
    apply heuristics to try to guess where the literal ends, or incorrectly
    color everything between the opening quote and the next closing quote
    as a string literal. This can cause the file's coloring to alternate
    distractingly between "string literal" and "running code".

    Continuation quotes give the syntax highlighter enough context to guess
    at the correct coloration, even when the string isn't complete yet.
    Lines with a continuation quote are literals; lines without are code.
    At worst, the syntax highlighter might incorrectly color a few
    characters at the end of a line, rather than the remainder of the file.

3.

    They separate indentation from the string's contents. Traditional
    multiline strings usually include all of the content between the start
    and end delimiters, including leading whitespace. This means that it's
    usually impossible to indent a multiline string, so including one
    breaks up the flow of the surrounding code, making it less readable.
    Some languages apply heuristics or mode switches to try to remove
    indentation, but like all heuristics, these are mistake-prone and murky.

    Continuation quotes neatly avoid this problem. Whitespace before the
    continuation quote is indentation used to format the source code;
    whitespace after the continuation quote is part of the string literal.
    The interpretation of the code is perfectly clear to both compiler and
    programmer.

4.

    They improve the ability to quickly recognize the literal. Traditional
    multiline strings don't provide much visual help. To find the end, you
    must visually scan until you find the matching delimiter, which may be
    only one or a few characters long. When looking at a random line of
    source, it can be hard to tell at a glance whether it's code or
    literal. Syntax highlighting can help with these issues, but it's often
    unreliable, especially with advanced, idiosyncratic string literal
    features like multiline strings.

    Continuation quotes solve these problems. To find the end of the
    literal, just scan down the column of continuation characters until
    they end. To figure out if a given line of source is part of a literal,
    just see if it starts with a quote mark. The meaning of the source
    becomes obvious at a glance.

Nevertheless, the traditional design /does/ has a few advantages:

1.

    *It is simpler.* Although continuation quotes are more complex, we
    believe that the advantages listed above pay for that complexity.

2.

    *There is no need to edit the intervening lines to add continuation
    quotes.* While the additional effort required to insert continuation
    quotes is an important downside, we believe that tool support,
    including both compiler fix-its and perhaps editor support for commands
    like "Paste as String Literal", can address this issue. In some
    editors, new features aren't even necessary; TextMate, for instance,
    lets you insert a character on several lines simultaneously. And new
    tool features could also address other issues like escaping embedded
    quotes.

3.

    *Naïve syntax highlighters may have trouble understanding this
    syntax.* This is true, but naïve syntax highlighters generally have
    terrible trouble with advanced string literal constructs; some struggle
    with even basic ones. While there are some designs (like
    Python's |"""| strings) which trick some syntax highlighters into
    working some of the time with some contents, we don't think this
    occasional, accidental compatibility is a big enough gain to justify
    changing the design.

4.

    *It looks funny—quotes should always be in matched pairs.* We aren't
    aware of another programming language which uses unbalanced quotes in
    string literals, but there /is/ one very important precedent for this
    kind of formatting: natural languages. English, for instance, uses a
    very similar format for quoting multiple lines of dialog by the same
    speaker. As an English Stack Exchange answer illustrates
    <punctuation - Why does the multi-paragraph quotation rule exist? - English Language & Usage Stack Exchange

        “That seems like an odd way to use punctuation,” Tom said. “What
        harm would there be in using quotation marks at the end of every
        paragraph?”

        “Oh, that’s not all that complicated,” J.R. answered. “If you
        closed quotes at the end of every paragraph, then you would need to
        reidentify the speaker with every subsequent paragraph.

        “Say a narrative was describing two or three people engaged in a
        lengthy conversation. If you closed the quotation marks in the
        previous paragraph, then a reader wouldn’t be able to easily tell
        if the previous speaker was extending his point, or if someone else
        in the room had picked up the conversation. By leaving the previous
        paragraph’s quote unclosed, the reader knows that the previous
        speaker is still the one talking.”

        “Oh, that makes sense. Thanks!”

    In English, omitting the ending quotation mark tells the text's reader
    that the quote continues on the next line, while including a quotation
    mark at the beginning of the next line reminds the reader that they're
    in the middle of a quote.

    Similarly, in this proposal, omitting the ending quotation mark tells
    the code's reader (and compiler) that the string literal continues on
    the next line, while including a quotation mark at the beginning of the
    next line reminds the reader (and compiler) that they're in the middle
    of a string literal.

On balance, we think continuation quotes are the best design for this problem.

    <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#detailed-design&gt;Detailed
    design

When Swift is parsing a string literal and reaches the end of a line
without finding a closing quote, it examines the next line, applying the
following rules:

1.

    If the next line begins with whitespace followed by a continuation
    quote, then the string literal contains a newline followed by the
    contents of the string literal starting on that line. (This line may
    itself have no closing quote, in which case the same rules apply to the
    line which follows.)

2.

    If the next line contains anything else, Swift raises a syntax error
    for an unterminated string literal.

The exact error messages and diagnostics provided are left to the
implementers to determine, but we believe it should be possible to provide
two fix-its which will help users learn the syntax and correct string
literal mistakes:

  *

    Insert |"| at the end of the current line to terminate the quote.

  *

    Insert |"| at the beginning of the next line (with some indentation
    heuristics) to continue the quote on the next line.

    <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#impact-on-existing-code&gt;Impact
    on existing code

Failing to close a string literal before the end of the line is currently a
syntax error, so no valid Swift code should be affected by this change.

    <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#future-directions-for-multiline-string-literals&gt;Future
    directions for multiline string literals

  *

    We could permit comments before encountering a continuation quote to be
    counted as whitespace, and permit empty lines in the middle of string
    literals. This would allow you to comment out whole lines in the literal.

  *

    We could allow you to put a trailing backslash on a line to indicate
    that the newline isn't "real" and should be omitted from the literal's
    contents.

    <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#future-directions-for-string-literals-in-general&gt;Future
    directions for string literals in general

There are other issues with Swift's string handling which this proposal
intentionally does not address:

  *

    Reducing the amount of double-backslashing needed when working with
    regular expression libraries, Windows paths, source code generation,
    and other tasks where backslashes are part of the data.

  *

    Alternate delimiters or other strategies for writing strings
    with |"| characters in them.

  *

    Accommodating code formatting concerns like hard wrapping and commenting.

  *

    String literals consisting of very long pieces of text which are best
    represented completely verbatim, with minimal alteration.

This section briefly outlines some future proposals which might address
these issues. Combined, we believe they would address most of the string
literal use cases which Swift is currently not very good at.

Please note that these are simply sketches of hypothetical future designs;
they may radically change before proposal, and some may never be proposed
at all. Many, perhaps most, will not be proposed for Swift 3. We are
sketching these designs not to propose and refine these features
immediately, but merely to show how we think they might be solved in ways
which complement this proposal.

      <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#string-literal-modifiers&gt;String
      literal modifiers

A string literal modifier is a cluster of identifier characters which goes
before a string literal and adjusts the way it is parsed. Modifers only
alter the interpretation of the text in the literal, not the type of data
it produces; for instance, there will never be something like the
UTF-8/UTF-16/UTF-32 literal modifiers in C++. Uppercase characters enable a
feature; lowercase characters disable a feature.

Modifiers can be attached to both single-line and multiline literals, and
could also be attached to other literal syntaxes which might be introduced
in the future. When used with multiline strings, only the starting quote
needs to carry the modifiers, not the continuation quotes.

Modifiers are an extremely flexible feature which can be used for many
proposes. Of the ideas listed below, we believe the |e| modifier is an
urgent addition which should be included in Swift 3 if at all possible; the
others are less urgent and most of them could be deferred, or at least
added later if time allows.

  *

    *Escape disabling*: |e"\\\"| (string with three backslash characters)

  *

    *Fine-grained escape disabling*: |i"\(foo)\n"| (the
    string |\(foo)| followed by a newline); |eI"\(foo)\n"| (the contents
    of |foo| followed by the string |\n|), |b"\w+\n"| (the
    string |\w+| followed by a newline)

  *

    *Alternate delimiters*: |_| has no lowercase form, so it could be used
    to allow strings with internal quotes: |_"print("Hello,
    world!")"_|, |__"print("Hello, world!")"__|, etc.

  *

    *Whitespace normalization*: changes all runs of whitespace in the
    literal to single space characters; this would allow you to use
    multiline strings purely to improve code formatting.

    >alert.informativeText = W"\(appName) could not typeset the element
    “\(title)” because "it includes a link to an element that has been
    removed from this "book." |

  *

    *Localization*:

    >alert.informativeText = LW"\(appName) could not typeset the element
    “\(title)” because "it includes a link to an element that has been
    removed from this "book." |

  *

    *Comments*: Embedding comments in string literals might be useful for
    literals containing regular expressions or other code.

Eventually, user-specified string modifiers could be added to Swift,
perhaps as part of a hygienic macro system. It might also become possible
to change the default modifiers applied to literals in a particular file or
scope.

      <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#heredocs-or-other-verbatim-string-literal-features&gt;Heredocs
      or other "verbatim string literal" features

Sometimes it really is best to just splat something else down in the middle
of a file full of Swift source code. Maybe the file is essentially a
template and the literals are a majority of the code's contents, or maybe
you're writing a code generator and just want to get string data into it
with minimal fuss, or maybe people unfamiliar with Swift need to be able to
edit the literals. Whatever the reason, the normal string literal syntax is
just too burdensome.

One approach to this problem is heredocs. A heredoc allows you to put a
placeholder for a literal on one line; the contents of the literal begin on
the next line, running up to some delimiter. It would be possible to put
multiple placeholders in a single line, and to apply string modifiers to them.

In Swift, this might look like:

print(#to("---") + e#to("END"))
It was a dark and stormy \(timeOfDay) when
---
the Swift core team invented the \(interpolation) syntax.
END

Another possible approach would be to support traditional multiline string
literals bounded by a different delimiter, like |"""|. This might look like:

print("""
It was a dark and stormy \(timeOfDay) when
""" + e"""
the Swift core team invented the \(interpolation) syntax.
""")

Although heredocs could make a good addition to Swift eventually, there are
good reasons to defer them for now. Please see the "Alternatives
considered" section for details.

      <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#first-class-regular-expressions&gt;First\-class
      regular expressions

Members of the core team are interested in regular expressions, but they
don't want to just build a literal that wraps PCRE or libicu; rather, they
aim to integrate regexes into the pattern matching system and give them a
deep, Perl 6-style rethink. This would be a major effort, far beyond the
scope of Swift 3.

In the meantime, the |e| modifier and perhaps other string literal
modifiers will make it easier to specify regular expressions in string
literals for use with |NSRegularExpression| and other libraries accessible
from Swift.

    <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#alternatives-considered&gt;Alternatives
    considered

      <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#requiring-no-continuation-character&gt;Requiring
      no continuation character

The main alternative is to not require a continuation quote, and simply
extend the string literal from the starting quote to the ending quote,
including all newlines between them. For example:

let xml = "<?xml version=\"1.0\"?>
<catalog>
<book id=\"bk101\" empty=\"\">
<author>\(author)</author>
</book>
</catalog>"

This alternative is extensively discussed in the "Rationale" section above.

      <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#skip-multiline-strings-and-just-support-heredocs&gt;Skip
      multiline strings and just support heredocs

There are definitely cases where a heredoc would be a better solution, such
as generated code or code which is mostly literals with a little Swift
sprinkled around. On the other hand, there are also cases where multiline
strings are better: short strings in code which is meant to be read. If a
single feature can't handle them both well, there's no shame in supporting
the two features separately.

It makes sense to support multiline strings first because:

  *

    They extend existing syntax instead of introducing new syntax.

  *

    They are much easier to parse; heredocs require some kind of mode in
    the parser which kicks in at the start of the next line, whereas
    multiline string literals can be handled in the lexer.

  *

    As discussed in "Rationale", they offer better diagnostics, code
    formatting, and visual scannability.

      <https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#use-a-different-delimiter-for-multiline-strings&gt;Use
      a different delimiter for multiline strings

The initial suggestion was that multiline strings should use a different
delimiter, |"""|, at the beginning and end of the string, with no
continuation characters between. Like heredocs, this might be a good
alternative for certain use cases, but it has the same basic flaws as the
"no continuation character" solution.

--
Brent Royal-Gordon
Architechies

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