multi-line string literals.


(Ted van Gaalen) #1

Hi.

The solutions discussed so far have the following disadvantages:
  - They need a specific delimiter token, which cannot be used in the text itself.
  - The data cannot be used as-is, escape \ characters are needed.
  - Imho, they are somewhat complicated.

In my emails previously submitted I came up with a "data line” concept,
a very simple solution, which tackles these disadvantages and is
very easy to use and understand!

Did you actually read it?
I now quote the primary description hereunder again, in case you’ve missed it,
imaginable, because there is a lot of text flying around.

Additionally, the following improvements have developed in my thinking:

In the mean time I consider using two tokens \\ and \@:
    \\…data…data…data…data………….. accepts data and converts \n \t etc.
or data lines starting with:
    \@…data…data…data…data… .……. accepts data as-is, without conversion and
                         respects the linefeeds of the source-file.

the // and /@ tokens do not have to start at the beginning of a line,
are allowed further to the right as long as there are only space(s) to the
left of it.

let music =
\\when Doves Cry\nBy Prince and
\\ The Revolution\nWhat music
\\ can be\t\t\t\tIt is \”Magic\” really.

If you do or don’t like this solution
-apart from cosmetic viewpoints-
please tell me why. so I can improve it,
or try to come back with something better if i can.

let epilogue =
\@Thank you so much for reading my
\@ “contribution" Please tell me
\@what you think, I \\\\\\\\\\\\\value//////////// your opinion!
\@“””””””””””””””””””””” kind Regards! “”””””””””””””””"
\@ Ted.

(the previous text following \@ data lines are accepted as-is, including
the source-file’s linefeeds or crlf and the double quotes)

Of course, other tokens are possible as well.

Can’t be any simpler than this, I guess.

TedvG

===================As Previously Written:=================

This could be a simple solution:

Starting each line with a special token.

In the example here it is the \\ double-backslash .
when the \\ appears in the first two columns of a source line,
this tells the compiler that it is a data line and that more might follow.
the last line starting with \\ completes the data entry.

Here is an example of a string declaration with some XML
(no escape sequences needed for “)
Of course it could be anything other kind of textual data as well.

let str =
\\<!DOCTYPE html>
\\<html>
\\<body>
\\
\\<h1>W3Schools Internal Note</h1>\n
\\<div>
\\<b>To:</b> <span id="to"></span><br>\n
\\<b>From:</b> <span id="from"></span><br>\n
\\<b>Message:</b> <span id="message"></span>
\\</div>
\\\n
\\<script>
\\var <smb://var> txt, parser, xmlDoc;
\\txt <smb://txt> = "<note>" +
\\"<to>Tove</to>" +
\\etc <smb://etc>. this is the last data line.

Conditions:

- Every line starting with \\ in first and second column of the line
  is treated as a data line.
- All characters behind the \\ are regarded as data, thus note that:
     - the “ is not regarded as a string delimiter
     - the // chars and whatever follows it are interpreted as data on such a line, not as comment.
     - \\ within the data itself are treated as data e.g. this line is valid:
\\There <smb://There> \\ are three backslashes (as data) in this line \\\\ today.
\\
the above data line is empty but is allowed.
for \\
- Leading and embedded spaces are respected.
- Tabs, Linefeeds etc. can be inserted the usual way using \t \n etc.
- trailing spaces and line terminators cr lf are ignored, filtered out.

···

============================================================

Wed, 27 Apr 2016 16:08:13 +0300"Vladimir.S" <svabox@gmail.com <mailto:svabox@gmail.com>> wrote:

On 27.04.2016 11:52, Brent Royal-Gordon via swift-evolution 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.

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

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>
* 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.
<https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160418/015500.html>

   <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
<http://english.stackexchange.com/a/96613/64636>:

   “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 <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(Vladimir) #2

Ted, please point me where in my suggestion you can find any of disadvantages you point in your message?

let xml = "\

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

"

"- They need a specific delimiter token, which cannot be used in the text
  itself." - no such delimiter
"- The data cannot be used as-is, escape \ characters are needed." - no need, text is *as-is* (just with | at the start, and I believe I can prove we need some start-of-line marker)
"- Imho, they are somewhat complicated." - ?? IMO clear and nice

···

On 27.04.2016 22:20, Ted F.A. van Gaalen wrote:

Hi.

The solutions discussed so far have the following disadvantages:
  - They need a specific delimiter token, which cannot be used in the text
itself.
  - The data cannot be used as-is, escape \ characters are needed.
  - Imho, they are somewhat complicated.

In my emails previously submitted I came up with a "data line” concept,
a very simple solution, which tackles these disadvantages and is
very easy to use and understand!

Did you actually read it?
I now quote the primary description hereunder again, in case you’ve missed it,
imaginable, because there is a lot of text flying around.

Additionally, the following improvements have developed in my thinking:

In the mean time I consider using two tokens \\ and \@:
    \\…data…data…data…data
<smb://%E2%80%A6data%E2%80%A6data%E2%80%A6data%E2%80%A6data>…………..
accepts data and converts \n \t etc.
or data lines starting with:
    \@…data…data…data…data… .……. accepts data as-is, without conversion and
                         respects the linefeeds of the source-file.

the // and /@ tokens do not have to start at the beginning of a line,
are allowed further to the right as long as there are only space(s) to the
left of it.

let music =
\\when <smb://when> Doves Cry\nBy Prince and
\\ The Revolution\nWhat music
\\ can be\t\t\t\tIt is \”Magic\” really.

If you do or don’t like this solution
-apart from cosmetic viewpoints-
please tell me why. so I can improve it,
or try to come back with something better if i can.

let epilogue =
\@Thank you so much for reading my
\@ “contribution" Please tell me
\@what you think, I \\\\\\\\\\\\\value//////////// your opinion!
\@“””””””””””””””””””””” kind Regards! “”””””””””””””””"
\@ Ted.

(the previous text following \@ data lines are accepted as-is, including
the source-file’s linefeeds or crlf and the double quotes)

Of course, other tokens are possible as well.

Can’t be any simpler than this, I guess.

TedvG

===================As Previously Written:=================

This could be a simple solution:

Starting each line with a special token.

In the example here it is the \\ double-backslash .
when the \\ appears in the first two columns of a source line,
this tells the compiler that it is a data line and that more might follow.
the last line starting with \\ completes the data entry.

Here is an example of a string declaration with some XML
(no escape sequences needed for “)
Of course it could be anything other kind of textual data as well.

let str =
\\<!DOCTYPE html>
\\<html>
\\<body>
\\
\\<h1>W3Schools Internal Note</h1>\n
\\<div>
\\<b>To:</b> <span id="to"></span><br>\n
\\<b>From:</b> <span id="from"></span><br>\n
\\<b>Message:</b> <span id="message"></span>
\\</div>
\\\n
\\<script>
\\var <smb://var> txt, parser, xmlDoc;
\\txt <smb://txt> = "<note>" +
\\"<to>Tove</to>" +
\\etc <smb://etc>. this is the last data line.

Conditions:

- Every line starting with \\ in first and second column of the line
  is treated as a data line.
- All characters behind the \\ are regarded as data, thus note that:
     - the “ is not regarded as a string delimiter
     - the // chars and whatever follows it are interpreted as data on such
a line, not as comment.
     - \\ within the data itself are treated as data e.g. this line is valid:
\\There <smb://There> \\ are three backslashes (as data) in this line \\\\
today.
\\
the above data line is empty but is allowed.
for \\
- Leading and embedded spaces are respected.
- Tabs, Linefeeds etc. can be inserted the usual way using \t \n etc.
- trailing spaces and line terminators cr lf are ignored, filtered out.

============================================================

Wed, 27 Apr 2016 16:08:13 +0300"Vladimir.S" <svabox@gmail.com
<mailto:svabox@gmail.com>> wrote:

On 27.04.2016 11:52, Brent Royal-Gordon via swift-evolution 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.

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

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>
* 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.
<https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160418/015500.html>

   <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
<http://english.stackexchange.com/a/96613/64636>:

   “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 <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution