<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><blockquote type="cite" class="">Brent, what is the state of the proposal document you prepared?<br class=""></blockquote><div class=""><br class=""></div>The state is that there is now a third draft, pasted below.<div class=""><br class=""></div><div class="">The main change in this version is that I've included a *lot* of rationale around what I think needs to be done to strings overall. This kind of bloats the proposal, but I'm not sure if there's a better way to make clear why it's tackling the problems it is.</div><div class=""><br class=""></div><div class="">John: I have not moved your trailing backslash suggestion back into the proposal yet, simply because I haven't decided how to write it up yet. I probably will unless others strongly think it should be subsetted out.</div><div class=""><br class=""></div><div class="">Dave: This obliquely addresses some of the points in your email, but I intend to reply more directly soon. Sorry, life has been happening to me during the last few days.</div><div class=""><div class="js-task-list-container file-box js-gist-file-update-container" style="box-sizing: border-box;"><form accept-charset="UTF-8" action="https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f/file/4d3f1f9e260a8e0e307bdda2c8e8ac8b2c9330a0" class="js-comment-update" data-form-nonce="768fbafa443af714264abba4eea7aa4cf85687c1" data-remote="true" method="post" style="box-sizing: border-box;"><div id="file-multiline-string-literals-md" class="file" style="box-sizing: border-box; position: relative; margin-top: 20px; margin-bottom: 15px; border: 1px solid rgb(221, 221, 221); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;"><div id="readme" class="readme blob instapaper_body" style="box-sizing: border-box;"><article class="markdown-body entry-content" itemprop="text" style="box-sizing: border-box; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; line-height: 1.6; word-wrap: break-word; padding: 45px; background-color: rgb(255, 255, 255); border: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; border-top-left-radius: 0px; border-top-right-radius: 0px;"><h1 style="box-sizing: border-box; font-size: 2.25em; margin-right: 0px; margin-bottom: 16px; margin-left: 0px; line-height: 1.2; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); margin-top: 0px !important;" class="">Multiline string literals</h1><ul style="box-sizing: border-box; padding-left: 2em; margin-top: 0px; margin-bottom: 16px;" class=""><li style="box-sizing: border-box;" class="">Proposal: <a href="https://github.com/apple/swift-evolution/blob/master/proposals/NNNN-name.md" style="box-sizing: border-box; background-color: transparent; -webkit-text-decoration-skip: objects; color: rgb(64, 120, 192); text-decoration: none;" class="">SE-NNNN</a></li><li style="box-sizing: border-box;" class="">Author(s): <a href="https://github.com/brentdax" style="box-sizing: border-box; background-color: transparent; -webkit-text-decoration-skip: objects; color: rgb(64, 120, 192); text-decoration: none;" class="">Brent Royal-Gordon</a>, <a href="https://github.com/johnno1962" style="box-sizing: border-box; background-color: transparent; -webkit-text-decoration-skip: objects; color: rgb(64, 120, 192); text-decoration: none;" class="">John Holdsworth</a>, <a href="https://github.com/TheArtOfEngineering" style="box-sizing: border-box; background-color: transparent; -webkit-text-decoration-skip: objects; color: rgb(64, 120, 192); text-decoration: none;" class="">Tyler Cloutier</a></li><li style="box-sizing: border-box;" class="">Status: <span style="box-sizing: border-box;" class=""><b class="">Third Draft</b></span></li><li style="box-sizing: border-box;" class="">Review manager: TBD</li></ul><h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238);" class=""><a id="user-content-introduction" class="anchor" href="https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#introduction" aria-hidden="true" style="box-sizing: border-box; background-color: transparent; -webkit-text-decoration-skip: objects; color: rgb(64, 120, 192); text-decoration: none; display: inline-block; padding-right: 2px; margin-left: -18px; line-height: 1;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Introduction</h2><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">In Swift 2.2, the only means to insert a newline into a string literal is the <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">\n</code> escape. String literals specified in this way are generally ugly and unreadable. We propose a multiline string feature emphasizing code readability which is a straightforward extension of our existing string literals and appears to be exceptionally easy to implement.</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">This proposal is the first step in a larger plan to improve how string literals address various challenging use cases. By itself, it is not meant to solve all problems with string escaping or the representation of long string literals. However, it is an important step in that direction, and it does modestly improve on the status quo even for those use cases which we intend to address more directly later.</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">See the "Motivation" section for the overall goals of this project, and the "Future directions for string literals in general" section for a sketch of how we might achieve those goals.</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">Swift-evolution threads: <a href="https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160418/015500.html" style="box-sizing: border-box; background-color: transparent; -webkit-text-decoration-skip: objects; color: rgb(64, 120, 192); text-decoration: none;" class="">multi-line string literals. (April)</a>, <a href="https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151214/002349.html" style="box-sizing: border-box; background-color: transparent; -webkit-text-decoration-skip: objects; color: rgb(64, 120, 192); text-decoration: none;" class="">multi-line string literals (December)</a></p><h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238);" class=""><a id="user-content-third-draft-notes" class="anchor" href="https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#third-draft-notes" aria-hidden="true" style="box-sizing: border-box; background-color: transparent; -webkit-text-decoration-skip: objects; color: rgb(64, 120, 192); text-decoration: none; display: inline-block; padding-right: 2px; margin-left: -18px; line-height: 1;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Third draft notes</h2><ul style="box-sizing: border-box; padding-left: 2em; margin-top: 0px; margin-bottom: 16px;" class=""><li style="box-sizing: border-box;" class=""><p style="box-sizing: border-box; margin-top: 16px; margin-bottom: 16px;" class="">Expands the "Motivation" section to discuss the overall string improvement project, including a list of goals, and reworks the "Future directions for string literals in general" section to theme it around the new list of goals and to discuss the sketched designs and some alternatives in more detail.</p></li><li style="box-sizing: border-box;" class=""><p style="box-sizing: border-box; margin-top: 16px; margin-bottom: 16px;" class="">Added a change to the formal grammar.</p></li><li style="box-sizing: border-box;" class=""><p style="box-sizing: border-box; margin-top: 16px; margin-bottom: 16px;" class="">Added discussion of John Holdsworth's prototype and the implementation lessons from it.</p></li><li style="box-sizing: border-box;" class=""><p style="box-sizing: border-box; margin-top: 16px; margin-bottom: 16px;" class="">Fills in co-authors. (I did the proposal drafting, John did the prototyping, and Tyler had the original idea and offered particularly detailed critiques.)</p></li></ul><h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238);" class=""><a id="user-content-motivation" class="anchor" href="https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#motivation" aria-hidden="true" style="box-sizing: border-box; background-color: transparent; -webkit-text-decoration-skip: objects; color: rgb(64, 120, 192); text-decoration: none; display: inline-block; padding-right: 2px; margin-left: -18px; line-height: 1;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Motivation</h2><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">Swift's string literals include the minimum viable feature set: they have quoting and escaping features sufficient to embed any Unicode string in a Swift source code file. They also support interpolation, a feature which makes constructing strings from dynamic data much easier. This is a great foundation for Swift string handling.</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">However, as Swift begins to move into roles beyond native app development, code which needs to generate text becomes a more important use case. Whether you're emitting HTML or XML, writing configuration files, generating source code in Swift or another language, or just showing long textual messages to the user, you need string literals to be more than just "minimum viable". We must move beyond that, making it easy and even pleasant to embed long, complex, and special-character-ridden strings into Swift code.</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">There are four very important areas where we think string literals need to improve:</p><ol style="box-sizing: border-box; padding-left: 2em; margin-top: 0px; margin-bottom: 16px;" class=""><li style="box-sizing: border-box;" class="">Putting newlines in string literals.</li><li style="box-sizing: border-box;" class="">Putting backslashes in string literals.</li><li style="box-sizing: border-box;" class="">Putting quote marks in string literals.</li><li style="box-sizing: border-box;" class="">Putting very large quantities of text (more than, say, twenty lines) in string literals.</li></ol><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">Swift's design principles call for an incremental approach to design, so <span style="box-sizing: border-box;" class="">this proposal only considers the first of these four goals.</span> We intend to address the others in separate but compatible future proposals, with the goal of fixing at least two in Swift 3 and all four by the time Swift 4 is released. A sketch of one possible design for these features is included in the "Future directions for string literals in general" section below.</p><h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em;" class=""><a id="user-content-an-aside-small-and-large-multiline-strings" class="anchor" href="https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#an-aside-small-and-large-multiline-strings" aria-hidden="true" style="box-sizing: border-box; background-color: transparent; -webkit-text-decoration-skip: objects; color: rgb(64, 120, 192); text-decoration: none; display: inline-block; padding-right: 2px; margin-left: -18px; line-height: 1.2;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>An aside: Small and large multiline strings</h3><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">The first entry in the list above, "Putting newlines in string literals", might be thought of as a subset of the fourth, "putting very large quantities of text in string literals". (In fact, <em style="box-sizing: border-box;" class="">all</em> of the entries could perhaps be subsumed by the fourth.) However, we believe they are best addressed as separate goals, using separate features.</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">When you are embedding enormous string literals in source code, you must put undistorted representation of the string above all other considerations. If the design which best permits the string to be written verbatim is ugly, bulky, unlike other language constructs, disruptive to code readability, error-prone, arbitrary, difficult to parse, or otherwise a wart on the language, that is simply the price we have to pay for that feature.</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">But it's a different story for short multiline strings. When you are writing a little bit of text, but still more than one line, you don't want to disrupt your code's indentation, add whole lines just for delimiters, insert bizarre or cryptic tokens into your code, or create syntax errors which take ten minutes to trace back to their source. You want a different feature, with different tradeoffs.</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">It is that feature which we propose.</p><h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em;" class=""><a id="user-content-the-goal-newlines-in-string-literals" class="anchor" href="https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#the-goal-newlines-in-string-literals" aria-hidden="true" style="box-sizing: border-box; background-color: transparent; -webkit-text-decoration-skip: objects; color: rgb(64, 120, 192); text-decoration: none; display: inline-block; padding-right: 2px; margin-left: -18px; line-height: 1.2;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>The goal: Newlines in string literals</h3><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">Consider a piece of code which generates a small XML string:</p><div class="highlight highlight-source-swift" style="box-sizing: border-box; margin-bottom: 16px;"><pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; margin-top: 0px; margin-bottom: 0px; line-height: 1.45; padding: 16px; overflow: auto; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-wrap: normal; word-break: normal;" class=""><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">let</span> xml <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><?xml version=<span class="pl-cce" style="box-sizing: border-box;">\"</span>1.0<span class="pl-cce" style="box-sizing: border-box;">\"</span>?><span class="pl-cce" style="box-sizing: border-box;">\n</span><catalog><span class="pl-cce" style="box-sizing: border-box;">\n\t</span><book id=<span class="pl-cce" style="box-sizing: border-box;">\"</span>bk101<span class="pl-cce" style="box-sizing: border-box;">\"</span> empty=<span class="pl-cce" style="box-sizing: border-box;">\"\"</span>><span class="pl-cce" style="box-sizing: border-box;">\n\t\t</span><author><span class="pl-pse" style="box-sizing: border-box;">\(</span><span class="pl-s1" style="box-sizing: border-box; color: rgb(51, 51, 51);">author</span><span class="pl-pse" style="box-sizing: border-box;">)</span></author><span class="pl-cce" style="box-sizing: border-box;">\n\t</span></book><span class="pl-cce" style="box-sizing: border-box;">\n</span></catalog><span class="pl-pds" style="box-sizing: border-box;">"</span></span></pre></div><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">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 <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">\t</code> escapes:</p><div class="highlight highlight-source-swift" style="box-sizing: border-box; margin-bottom: 16px;"><pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; margin-top: 0px; margin-bottom: 0px; line-height: 1.45; padding: 16px; overflow: auto; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-wrap: normal; word-break: normal;" class=""><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">let</span> xml <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><?xml version=<span class="pl-cce" style="box-sizing: border-box;">\"</span>1.0<span class="pl-cce" style="box-sizing: border-box;">\"</span>?><span class="pl-cce" style="box-sizing: border-box;">\n</span><span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">+</span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><catalog><span class="pl-cce" style="box-sizing: border-box;">\n</span><span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">+</span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span> <book id=<span class="pl-cce" style="box-sizing: border-box;">\"</span>bk101<span class="pl-cce" style="box-sizing: border-box;">\"</span> empty=<span class="pl-cce" style="box-sizing: border-box;">\"\"</span>><span class="pl-cce" style="box-sizing: border-box;">\n</span><span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">+</span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span> <author><span class="pl-pse" style="box-sizing: border-box;">\(</span><span class="pl-s1" style="box-sizing: border-box; color: rgb(51, 51, 51);">author</span><span class="pl-pse" style="box-sizing: border-box;">)</span></author><span class="pl-cce" style="box-sizing: border-box;">\n</span><span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">+</span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span> </book><span class="pl-cce" style="box-sizing: border-box;">\n</span><span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">+</span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span></catalog><span class="pl-pds" style="box-sizing: border-box;">"</span></span></pre></div><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">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.</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">The example above generates XML, but there are many similar cases where a short fragment of text including newlines must be included in a string literal:</p><ul style="box-sizing: border-box; padding-left: 2em; margin-top: 0px; margin-bottom: 16px;" class=""><li style="box-sizing: border-box;" class="">Generating HTML, a task which will hopefully become more common</li><li style="box-sizing: border-box;" class="">Generating error messages and other user-facing text, in both graphical and command-line interfaces</li><li style="box-sizing: border-box;" class="">Generating configuration files and other "scripty" tasks</li><li style="box-sizing: border-box;" class="">Generating messages for other text-based protocols and formats</li><li style="box-sizing: border-box;" class="">Generating Swift code (common to work around the current lack of metaprogramming features other than generics)</li><li style="box-sizing: border-box;" class="">Generating code in general</li></ul><h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238);" class=""><a id="user-content-proposed-solution" class="anchor" href="https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#proposed-solution" aria-hidden="true" style="box-sizing: border-box; background-color: transparent; -webkit-text-decoration-skip: objects; color: rgb(64, 120, 192); text-decoration: none; display: inline-block; padding-right: 2px; margin-left: -18px; line-height: 1;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Proposed solution</h2><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">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.</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">Our sample above could thus be written as:</p><pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; margin-top: 0px; margin-bottom: 16px; line-height: 1.45; padding: 16px; overflow: auto; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-wrap: normal;" class=""><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-break: normal; border: 0px; display: inline; line-height: inherit; word-wrap: normal;" class="">let xml = "<?xml version=\"1.0\"?>
"<catalog>
" <book id=\"bk101\" empty=\"\">
" <author>\(author)</author>
" </book>
"</catalog>"
</code></pre><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">If the second or subsequent lines had not begun with a quotation mark, or the trailing quotation mark after the <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class=""></catalog></code>tag had not been included, Swift would have emitted an error.</p><h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em;" class=""><a id="user-content-rationale" class="anchor" href="https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#rationale" aria-hidden="true" style="box-sizing: border-box; background-color: transparent; -webkit-text-decoration-skip: objects; color: rgb(64, 120, 192); text-decoration: none; display: inline-block; padding-right: 2px; margin-left: -18px; line-height: 1.2;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Rationale</h3><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">This design is rather unusual, and it's worth pausing for a moment to explain why it has been chosen.</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">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. </p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">We think continuation quotes offer several important advantages over the traditional design:</p><ol style="box-sizing: border-box; padding-left: 2em; margin-top: 0px; margin-bottom: 16px;" class=""><li style="box-sizing: border-box;" class=""><p style="box-sizing: border-box; margin-top: 16px; margin-bottom: 16px;" class=""><span style="box-sizing: border-box;" class=""><b class="">They help the compiler pinpoint errors in string literal delimiting.</b></span> 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.</p><p style="box-sizing: border-box; margin-top: 16px; margin-bottom: 16px;" class="">(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.)</p><p style="box-sizing: border-box; margin-top: 16px; margin-bottom: 16px;" class="">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 <em style="box-sizing: border-box;" class="">end</em> of the literal, where you want to insert the quote, rather than showing you the <em style="box-sizing: border-box;" class="">beginning</em> of the literal or even some unrelated error later in the file that was caused by the missing quote.</p></li><li style="box-sizing: border-box;" class=""><p style="box-sizing: border-box; margin-top: 16px; margin-bottom: 16px;" class=""><span style="box-sizing: border-box;" class=""><b class="">Temporarily unclosed literals don't make editors go haywire.</b></span> The syntax highlighter has the same trouble parsing half-written, unclosed string literals 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".</p><p style="box-sizing: border-box; margin-top: 16px; margin-bottom: 16px;" class="">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.</p></li><li style="box-sizing: border-box;" class=""><p style="box-sizing: border-box; margin-top: 16px; margin-bottom: 16px;" class=""><span style="box-sizing: border-box;" class=""><b class="">They separate indentation from the string's contents.</b></span> 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, either at compile time or through runtime string manipulation functions, to try to remove indentation, but like all heuristics, these are mistake-prone and murky.</p><p style="box-sizing: border-box; margin-top: 16px; margin-bottom: 16px;" class="">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.</p></li><li style="box-sizing: border-box;" class=""><p style="box-sizing: border-box; margin-top: 16px; margin-bottom: 16px;" class=""><span style="box-sizing: border-box;" class=""><b class="">They improve the ability to quickly recognize the literal.</b></span> 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.</p><p style="box-sizing: border-box; margin-top: 16px; margin-bottom: 16px;" class="">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.</p></li></ol><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">Nevertheless, the traditional design <em style="box-sizing: border-box;" class="">does</em> has a few advantages:</p><ol style="box-sizing: border-box; padding-left: 2em; margin-top: 0px; margin-bottom: 16px;" class=""><li style="box-sizing: border-box;" class=""><p style="box-sizing: border-box; margin-top: 16px; margin-bottom: 16px;" class=""><span style="box-sizing: border-box;" class=""><b class="">It is simpler.</b></span> Although continuation quotes are more complex, we believe that the advantages listed above pay for that complexity.</p></li><li style="box-sizing: border-box;" class=""><p style="box-sizing: border-box; margin-top: 16px; margin-bottom: 16px;" class=""><span style="box-sizing: border-box;" class=""><b class="">There is no need to edit the intervening lines to add continuation quotes.</b></span> 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. These features could also address other issues like escaping. And many editors already support features which permit you to insert the same character at the same column in many adjacent lines—the exact task required to add continuation quotes.</p></li><li style="box-sizing: border-box;" class=""><p style="box-sizing: border-box; margin-top: 16px; margin-bottom: 16px;" class=""><span style="box-sizing: border-box;" class=""><b class="">Simple syntax highlighters may not support this syntax.</b></span> This is true, but simple, generic 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 <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">"""</code> strings) which trick some syntax highlighters into working with some contents, we think the code formatting and visual recognition gains described above assist code reading more than the loss of finicky partial syntax highlighting compatibility hinders it.</p></li><li style="box-sizing: border-box;" class=""><p style="box-sizing: border-box; margin-top: 16px; margin-bottom: 16px;" class=""><span style="box-sizing: border-box;" class=""><b class="">It looks funny—quotes should always be in matched pairs.</b></span> We aren't aware of another programming language which uses unbalanced quotes in string literals, but there <em style="box-sizing: border-box;" class="">is</em> 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. (Nor is this an English-only quirk; Spanish and French, the other two languages I checked, seem to have similar conventions.)</p><p style="box-sizing: border-box; margin-top: 16px; margin-bottom: 16px;" class="">As <a href="http://english.stackexchange.com/a/96613/64636" style="box-sizing: border-box; background-color: transparent; -webkit-text-decoration-skip: objects; color: rgb(64, 120, 192); text-decoration: none;" class="">an English Stack Exchange answer illustrates</a>:</p><blockquote style="box-sizing: border-box; margin: 0px 0px 16px; padding: 0px 15px; color: rgb(119, 119, 119); border-left-width: 4px; border-left-style: solid; border-left-color: rgb(221, 221, 221);" class=""><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">“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?”</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">“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.</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">“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.”</p><div style="box-sizing: border-box; margin-top: 0px; margin-bottom: 0px;" class="">“Oh, that makes sense. Thanks!”</div></blockquote><p style="box-sizing: border-box; margin-top: 16px; margin-bottom: 16px;" class="">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.</p><p style="box-sizing: border-box; margin-top: 16px; margin-bottom: 16px;" class="">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.</p></li></ol><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">On balance, we think continuation quotes are the best design for this problem.</p><h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238);" class=""><a id="user-content-detailed-design" class="anchor" href="https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#detailed-design" aria-hidden="true" style="box-sizing: border-box; background-color: transparent; -webkit-text-decoration-skip: objects; color: rgb(64, 120, 192); text-decoration: none; display: inline-block; padding-right: 2px; margin-left: -18px; line-height: 1;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Detailed design</h2><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">When Swift is parsing a string literal and reaches the end of a line without finding an end quote, it examines the next line, applying the following rules:</p><ol style="box-sizing: border-box; padding-left: 2em; margin-top: 0px; margin-bottom: 16px;" class=""><li style="box-sizing: border-box;" class=""><p style="box-sizing: border-box; margin-top: 16px; margin-bottom: 16px;" class="">If the next line begins with a quote mark (skipping horizontal whitespace), then the string literal contains a newline followed by the contents of the string literal starting after the quote mark. (This line may itself have no end quote, in which case the same rules apply to the line which follows.)</p></li><li style="box-sizing: border-box;" class=""><p style="box-sizing: border-box; margin-top: 16px; margin-bottom: 16px;" class="">If the next line begins with anything else, Swift raises a syntax error for an unterminated string literal. </p></li></ol><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">Formally, the following grammar productions (from <em style="box-sizing: border-box;" class="">The Swift Programming Language</em>):</p><pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; margin-top: 0px; margin-bottom: 16px; line-height: 1.45; padding: 16px; overflow: auto; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-wrap: normal;" class=""><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-break: normal; border: 0px; display: inline; line-height: inherit; word-wrap: normal;" class="">static-string-literal → '"' quoted-text(opt) '"'
interpolated-string-literal → '"' interpolated-text(opt) '"'
</code></pre><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">Become something like:</p><pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; margin-top: 0px; margin-bottom: 16px; line-height: 1.45; padding: 16px; overflow: auto; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-wrap: normal;" class=""><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-break: normal; border: 0px; display: inline; line-height: inherit; word-wrap: normal;" class="">discarded-whitespace → (zero or more horizontal whitespace characters)
static-string-literal → '"' quoted-text(opt) '"'
| '"' quoted-text(opt) \n discarded-whitespace static-string-literal
interpolated-string-literal → '"' interpolated-text(opt) '"'
| '"' interpolated-text(opt) \n discarded-whitespace interpolated-string-literal
</code></pre><h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em;" class=""><a id="user-content-diagnostics" class="anchor" href="https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#diagnostics" aria-hidden="true" style="box-sizing: border-box; background-color: transparent; -webkit-text-decoration-skip: objects; color: rgb(64, 120, 192); text-decoration: none; display: inline-block; padding-right: 2px; margin-left: -18px; line-height: 1.2;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Diagnostics</h3><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">The exact error messages and diagnostics provided for unterminated quotes 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:</p><ul style="box-sizing: border-box; padding-left: 2em; margin-top: 0px; margin-bottom: 16px;" class=""><li style="box-sizing: border-box;" class=""><p style="box-sizing: border-box; margin-top: 16px; margin-bottom: 16px;" class="">Insert <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">"</code> at the end of the current line to terminate the quote.</p></li><li style="box-sizing: border-box;" class=""><p style="box-sizing: border-box; margin-top: 16px; margin-bottom: 16px;" class="">Insert <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">"</code> at the beginning of the next line (with some indentation heuristics) to continue the quote on the next line.</p></li></ul><h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em;" class=""><a id="user-content-prototypes-and-samples" class="anchor" href="https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#prototypes-and-samples" aria-hidden="true" style="box-sizing: border-box; background-color: transparent; -webkit-text-decoration-skip: objects; color: rgb(64, 120, 192); text-decoration: none; display: inline-block; padding-right: 2px; margin-left: -18px; line-height: 1.2;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Prototypes and samples</h3><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class=""><a href="https://github.com/apple/swift/pull/2275" style="box-sizing: border-box; background-color: transparent; -webkit-text-decoration-skip: objects; color: rgb(64, 120, 192); text-decoration: none;" class="">John Holdsworth's pull request</a> includes prototypes of several of the features we are planning, including this multiline string proposal. The pull request includes a link to a pre-built Swift toolchain containing the prototypes, which you can download and install to try these features for yourself.</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">The multiline strings prototype seems to indicate that the footprint of this feature will be very small. The changes for this proposal are confined entirely to the <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">Lexer</code> methods <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">lexStringLiteral()</code>, <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">lexCharacter()</code>, and <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">getEncodedStringSegment()</code>. (The string literal modifier feature impacts other parts of the lexer, but this proposal doesn't require those changes.) The prototype's diagnostics are primitive, and improving them would probably increase the impacted code, but it seems likely that the required changes will be very localized.</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">A very small ad-hoc set of tests for parts of the prototyped features is available <a href="https://gist.github.com/brentdax/be3c032bc7e0c101d7ba8b72cd1a692e#file-quotetest-swift-L91" style="box-sizing: border-box; background-color: transparent; -webkit-text-decoration-skip: objects; color: rgb(64, 120, 192); text-decoration: none;" class="">in this gist</a>. It is more demo than comprehensive test suite, but it shows a couple of ways this proposal and the other proposed features might be used, together and separately.</p><h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238);" class=""><a id="user-content-impact-on-existing-code" class="anchor" href="https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#impact-on-existing-code" aria-hidden="true" style="box-sizing: border-box; background-color: transparent; -webkit-text-decoration-skip: objects; color: rgb(64, 120, 192); text-decoration: none; display: inline-block; padding-right: 2px; margin-left: -18px; line-height: 1;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Impact on existing code</h2><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">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.</p><h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238);" class=""><a id="user-content-future-directions-for-multiline-string-literals" class="anchor" href="https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#future-directions-for-multiline-string-literals" aria-hidden="true" style="box-sizing: border-box; background-color: transparent; -webkit-text-decoration-skip: objects; color: rgb(64, 120, 192); text-decoration: none; display: inline-block; padding-right: 2px; margin-left: -18px; line-height: 1;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Future directions for multiline string literals</h2><ul style="box-sizing: border-box; padding-left: 2em; margin-top: 0px; margin-bottom: 16px;" class=""><li style="box-sizing: border-box;" class=""><p style="box-sizing: border-box; margin-top: 16px; margin-bottom: 16px;" class="">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.</p></li><li style="box-sizing: border-box;" class=""><p style="box-sizing: border-box; margin-top: 16px; margin-bottom: 16px;" class="">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. Holdsworth's prototype includes this feature.</p></li></ul><h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238);" class=""><a id="user-content-future-directions-for-string-literals-in-general" class="anchor" href="https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#future-directions-for-string-literals-in-general" aria-hidden="true" style="box-sizing: border-box; background-color: transparent; -webkit-text-decoration-skip: objects; color: rgb(64, 120, 192); text-decoration: none; display: inline-block; padding-right: 2px; margin-left: -18px; line-height: 1;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Future directions for string literals in general</h2><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">In the "Motivation" section, we identified four goals for improvements in Swift string literals:</p><ol style="box-sizing: border-box; padding-left: 2em; margin-top: 0px; margin-bottom: 16px;" class=""><li style="box-sizing: border-box;" class="">Putting newlines in string literals.</li><li style="box-sizing: border-box;" class="">Putting backslashes in string literals.</li><li style="box-sizing: border-box;" class="">Putting quote marks in string literals.</li><li style="box-sizing: border-box;" class="">Putting very large quantities of text (more than, say, twenty lines) in string literals.</li></ol><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">This proposal addresses #1. Let's sketch some solutions for the other three, as well as related features we might enable along the way.</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">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.</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">What is most important about these designs is how they all work together with each other, with the current proposal, and with existing Swift string literals. Rather than inventing a new kind of string literal for each feature, we want to, where possible, extend and reuse existing syntax features.</p><h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em;" class=""><a id="user-content-a-general-mechanism-string-literal-modifiers" class="anchor" href="https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#a-general-mechanism-string-literal-modifiers" aria-hidden="true" style="box-sizing: border-box; background-color: transparent; -webkit-text-decoration-skip: objects; color: rgb(64, 120, 192); text-decoration: none; display: inline-block; padding-right: 2px; margin-left: -18px; line-height: 1.2;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>A general mechanism: String literal modifiers</h3><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">We may introduce the concept of string literal modifiers to alter the interpretation of string literals. These would become the basis for many future string literal features.</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">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++. </p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">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.</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">In one potential design, uppercase modifier characters enable a feature; lowercase characters disable a feature.</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">Our prototype also includes basic support for string modifiers, although the specific behavior of the modifiers in the prototype doesn't precisely match this sketch.</p><h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em;" class=""><a id="user-content-goal-2-backslashes" class="anchor" href="https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#goal-2-backslashes" aria-hidden="true" style="box-sizing: border-box; background-color: transparent; -webkit-text-decoration-skip: objects; color: rgb(64, 120, 192); text-decoration: none; display: inline-block; padding-right: 2px; margin-left: -18px; line-height: 1.2;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Goal 2: Backslashes</h3><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">In the simplest version of this feature, we could add an <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">e</code>/<code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">E</code> string literal modifier which enables all backslash-based escaping, including interpolation, double backslash, and backslash-quote. An <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">e</code> string would treat all backslashes literally, while an <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">E</code> string would treat all backslashes as escapes of some sort. <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">E</code> (the current behavior) would be the default. Thus, these would print:</p><div class="highlight highlight-source-swift" style="box-sizing: border-box; margin-bottom: 16px;"><pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; margin-top: 0px; margin-bottom: 0px; line-height: 1.45; padding: 16px; overflow: auto; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-wrap: normal; word-break: normal;" class=""><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">print</span>(e<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-cce" style="box-sizing: border-box;">\\\"</span>)</span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"> => <span class="pl-cce" style="box-sizing: border-box;">\\</span>\</span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);">print(e<span class="pl-pds" style="box-sizing: border-box;">"</span></span>C:\Program Files\Microsoft <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Word</span><span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>)</span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"> => C:<span class="pl-ii" style="box-sizing: border-box; background-color: rgb(181, 42, 29); color: rgb(248, 248, 248);">\P</span>rogram Files<span class="pl-ii" style="box-sizing: border-box; background-color: rgb(181, 42, 29); color: rgb(248, 248, 248);">\M</span>icrosoft Word</span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);">print(e<span class="pl-pds" style="box-sizing: border-box;">"</span></span>\w<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">+</span><span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>)</span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"> => <span class="pl-ii" style="box-sizing: border-box; background-color: rgb(181, 42, 29); color: rgb(248, 248, 248);">\w</span>+</span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);">print(e<span class="pl-pds" style="box-sizing: border-box;">"</span></span>Interpolation looks like
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pse" style="box-sizing: border-box;">\(</span><span class="pl-s1" style="box-sizing: border-box; color: rgb(51, 51, 51);">this</span><span class="pl-pse" style="box-sizing: border-box;">)</span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>)
<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=></span> Interpolation looks like
<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=></span> \(this)</pre></div><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">We might also allow you to enable or disable individual features. For instance, <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">i</code> might control interpolation, <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">q</code> might control quotes, and <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">b</code> might control other backslashes. Thus:</p><div class="highlight highlight-source-swift" style="box-sizing: border-box; margin-bottom: 16px;"><pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; margin-top: 0px; margin-bottom: 0px; line-height: 1.45; padding: 16px; overflow: auto; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-wrap: normal; word-break: normal;" class=""><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">print</span>(i<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>Interpolation looks like <span class="pl-cce" style="box-sizing: border-box;">\"</span><span class="pl-pse" style="box-sizing: border-box;">\(</span><span class="pl-s1" style="box-sizing: border-box; color: rgb(51, 51, 51);">this</span><span class="pl-pse" style="box-sizing: border-box;">)</span><span class="pl-cce" style="box-sizing: border-box;">\"</span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>)
<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=></span> Interpolation looks like <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pse" style="box-sizing: border-box;">\(</span><span class="pl-s1" style="box-sizing: border-box; color: rgb(51, 51, 51);">this</span><span class="pl-pse" style="box-sizing: border-box;">)</span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>
<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">print</span>(eI<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>C:<span class="pl-ii" style="box-sizing: border-box; background-color: rgb(181, 42, 29); color: rgb(248, 248, 248);">\P</span>rogram Files<span class="pl-cce" style="box-sizing: border-box;">\\</span>(programName)<span class="pl-pds" style="box-sizing: border-box;">"</span></span>)
<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=></span> C:\Program Files\Microsoft <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">Word</span>
<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">print</span>(b<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-ii" style="box-sizing: border-box; background-color: rgb(181, 42, 29); color: rgb(248, 248, 248);">\w</span>+<span class="pl-cce" style="box-sizing: border-box;">\n</span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>)
<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=></span> \w<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">+</span>
<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=></span> </pre></div><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">These could be proposed separately, with <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">e</code> coming in Swift 3 and more nuanced modifiers potentially waiting for Swift 4.</p><h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em;" class=""><a id="user-content-goal-3-quote-marks" class="anchor" href="https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#goal-3-quote-marks" aria-hidden="true" style="box-sizing: border-box; background-color: transparent; -webkit-text-decoration-skip: objects; color: rgb(64, 120, 192); text-decoration: none; display: inline-block; padding-right: 2px; margin-left: -18px; line-height: 1.2;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Goal 3: Quote Marks</h3><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">One possibility is to allow the user to put any number of <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">_</code> characters—a valid identifier character with no uppercase equivalent—between the modifier (if any) and the opening quote. The parser would then look for a matching number of <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">_</code>characters after any closing quote, and if it did not find them, it would treat the <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">"</code> as a character in the string literal. Thus:</p><div class="highlight highlight-source-swift" style="box-sizing: border-box; margin-bottom: 16px;"><pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; margin-top: 0px; margin-bottom: 0px; line-height: 1.45; padding: 16px; overflow: auto; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-wrap: normal; word-break: normal;" class=""><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">print</span>(_<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><a href=<span class="pl-pds" style="box-sizing: border-box;">"</span></span>\(url)<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>><span class="pl-pds" style="box-sizing: border-box;">"</span></span>_)
<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><</span>a href<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span><span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><a href="http://www.swift.org/" class="">http://www.swift.org/</a><span class="pl-pds" style="box-sizing: border-box;">"</span></span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">></span>
<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">print</span>(e_<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>print(<span class="pl-pds" style="box-sizing: border-box;">"</span></span>Hello, world<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">!</span>\n<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>)<span class="pl-pds" style="box-sizing: border-box;">"</span></span>_)
<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=></span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">print</span>(<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>Hello, world!<span class="pl-cce" style="box-sizing: border-box;">\n</span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>)
<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">print</span>(b_<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>[<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">^</span><span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-cce" style="box-sizing: border-box;">\\</span>]*(<span class="pl-cce" style="box-sizing: border-box;">\\</span>.[^<span class="pl-pds" style="box-sizing: border-box;">"</span></span><a href="smb://]" class="">\\]</a><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">*</span>)<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">*+</span><span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>_)
<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=></span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>[^<span class="pl-pds" style="box-sizing: border-box;">"</span></span>\\]<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">*</span>(\\<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">.</span>[<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">^</span><span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-cce" style="box-sizing: border-box;">\\</span>]*)*+<span class="pl-pds" style="box-sizing: border-box;">"</span></span></pre></div><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">Here are some other ways this feature could be implemented:</p><ul style="box-sizing: border-box; padding-left: 2em; margin-top: 0px; margin-bottom: 16px;" class=""><li style="box-sizing: border-box;" class="">Use a different identifier-but-not-capitalizable modifier, like <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">$"foo"$</code>.</li><li style="box-sizing: border-box;" class="">Use a different single-character ASCII delimiter, like <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">'foo'</code>.</li><li style="box-sizing: border-box;" class="">Use a different multi-character delimiter, like <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">"""foo"""</code>.</li><li style="box-sizing: border-box;" class="">Use a different Unicode delimiter, like smart quotes (<code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">“foo”</code>) or French quotes (<code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">«foo»</code>) or Japanese quotes (<code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">⸢foo⸥</code>).</li><li style="box-sizing: border-box;" class="">Permit arbitrary delimiters bounded by some specific, known character, like <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">'zyzyx'foo'zyzyx'</code>.</li></ul><h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em;" class=""><a id="user-content-goal-4-very-large-quantities-of-text" class="anchor" href="https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#goal-4-very-large-quantities-of-text" aria-hidden="true" style="box-sizing: border-box; background-color: transparent; -webkit-text-decoration-skip: objects; color: rgb(64, 120, 192); text-decoration: none; display: inline-block; padding-right: 2px; margin-left: -18px; line-height: 1.2;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Goal 4: Very large quantities of text</h3><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">As discussed in the "Motivation" section, when a string gets long enough, the most important feature of the quoting construct becomes fidelity to the text represented. When your string literal is 50 or 100 lines long, you don't want to mess around with prefixing lines with continuation quotes—you've already disrupted the flow of your program far more than outdenting the literal would, you're not likely to miss the enormous delimiter the feature provides, and the size of the literal will be obviously more than "a screenful" (and more obvious because it's not indented properly). You just want something that makes it as easy as possible to get the text into your source without fuss.</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">(Note: To keep this brief, I'll be using examples which are shorter than you would normally use this feature with.)</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">There are two main options here, which might broadly be thought of as "the Python way" (which we will call verbatim strings) and "the Perl way" (heredocs).</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">Verbatim strings are, quite simply, string literals bounded by <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">"""</code>. Between the two pairs of <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">"""</code> delimiters, you may put any character, including newlines.</p><div class="highlight highlight-source-swift" style="box-sizing: border-box; margin-bottom: 16px;"><pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; margin-top: 0px; margin-bottom: 0px; line-height: 1.45; padding: 16px; overflow: auto; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-wrap: normal; word-break: normal;" class=""><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">print</span>(<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span><?xml version=<span class="pl-pds" style="box-sizing: border-box;">"</span></span><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">.</span><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span><span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>?></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><catalog></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"> <book id=<span class="pl-pds" style="box-sizing: border-box;">"</span></span>bk101<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span> empty=<span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span>></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"> <author><span class="pl-pse" style="box-sizing: border-box;">\(</span><span class="pl-s1" style="box-sizing: border-box; color: rgb(51, 51, 51);">author</span><span class="pl-pse" style="box-sizing: border-box;">)</span></author></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"> </book></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"></catalog><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>)
<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">print</span>(<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span>It was a dark and </span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);">stormy <span class="pl-pse" style="box-sizing: border-box;">\(</span><span class="pl-s1" style="box-sizing: border-box; color: rgb(51, 51, 51);">timeOfDay</span><span class="pl-pse" style="box-sizing: border-box;">)</span> when <span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">+</span> e<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span>the Swift core team invented </span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);">the <span class="pl-pse" style="box-sizing: border-box;">\(</span><span class="pl-s1" style="box-sizing: border-box; color: rgb(51, 51, 51);">interpolation</span><span class="pl-pse" style="box-sizing: border-box;">)</span> syntax.<span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>)</pre></div><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">A variation on this would require the delimiters to be on separate lines from the string contents:</p><div class="highlight highlight-source-swift" style="box-sizing: border-box; margin-bottom: 16px;"><pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; margin-top: 0px; margin-bottom: 0px; line-height: 1.45; padding: 16px; overflow: auto; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-wrap: normal; word-break: normal;" class=""><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">print</span>(<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><?xml version=<span class="pl-pds" style="box-sizing: border-box;">"</span></span><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1</span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">.</span><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">0</span><span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>?></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><catalog></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"> <book id=<span class="pl-pds" style="box-sizing: border-box;">"</span></span>bk101<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span> empty=<span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span>></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"> <author><span class="pl-pse" style="box-sizing: border-box;">\(</span><span class="pl-s1" style="box-sizing: border-box; color: rgb(51, 51, 51);">author</span><span class="pl-pse" style="box-sizing: border-box;">)</span></author></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"> </book></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"></catalog></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>)
<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">print</span>(<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);">It was a dark and stormy </span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pse" style="box-sizing: border-box;">\(</span><span class="pl-s1" style="box-sizing: border-box; color: rgb(51, 51, 51);">timeOfDay</span><span class="pl-pse" style="box-sizing: border-box;">)</span> when </span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">+</span> e<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);">the Swift core team invented </span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);">the <span class="pl-pse" style="box-sizing: border-box;">\(</span><span class="pl-s1" style="box-sizing: border-box; color: rgb(51, 51, 51);">interpolation</span><span class="pl-pse" style="box-sizing: border-box;">)</span> syntax.</span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>)</pre></div><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">A very simple approach with generally similar features would be to introduce a modifier which disabled continuation quotes; in other words, it would turn this proposal's multiline strings into a more traditional version. If you needed an alternate delimiter, you could then use whatever alternate delimiter mechanism we introduce for normal string literals.</p><div class="highlight highlight-source-swift" style="box-sizing: border-box; margin-bottom: 16px;"><pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; margin-top: 0px; margin-bottom: 0px; line-height: 1.45; padding: 16px; overflow: auto; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-wrap: normal; word-break: normal;" class=""><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">print</span>(c_<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><?xml version=<span class="pl-cce" style="box-sizing: border-box;">\"</span>1.0<span class="pl-cce" style="box-sizing: border-box;">\"</span>?></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><catalog></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"> <book id=<span class="pl-cce" style="box-sizing: border-box;">\"</span>bk101<span class="pl-cce" style="box-sizing: border-box;">\"</span> empty=<span class="pl-cce" style="box-sizing: border-box;">\"\"</span>></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"> <author><span class="pl-pse" style="box-sizing: border-box;">\(</span><span class="pl-s1" style="box-sizing: border-box; color: rgb(51, 51, 51);">author</span><span class="pl-pse" style="box-sizing: border-box;">)</span></author></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"> </book></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"></catalog><span class="pl-pds" style="box-sizing: border-box;">"</span></span>_)
<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">print</span>(c<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>It was a dark and stormy </span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pse" style="box-sizing: border-box;">\(</span><span class="pl-s1" style="box-sizing: border-box; color: rgb(51, 51, 51);">timeOfDay</span><span class="pl-pse" style="box-sizing: border-box;">)</span> when <span class="pl-pds" style="box-sizing: border-box;">"</span></span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">+</span> ec<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>the Swift core team invented </span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);">the <span class="pl-pse" style="box-sizing: border-box;">\(</span><span class="pl-s1" style="box-sizing: border-box; color: rgb(51, 51, 51);">interpolation</span><span class="pl-pse" style="box-sizing: border-box;">)</span> syntax.<span class="pl-pds" style="box-sizing: border-box;">"</span></span>)</pre></div><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">Heredocs have you put a placeholder token in one line for a string literal whose contents begin on the next line. Traditionally, heredocs have allowed you to specify an arbitrary string as a delimiter, which must appear on its own line. The traditional syntax for heredocs would look something like:</p><div class="highlight highlight-source-swift" style="box-sizing: border-box; margin-bottom: 16px;"><pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; margin-top: 0px; margin-bottom: 0px; line-height: 1.45; padding: 16px; overflow: auto; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-wrap: normal; word-break: normal;" class=""><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">print</span>(<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><<</span><span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>END<span class="pl-pds" style="box-sizing: border-box;">"</span></span>)
<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><</span>?xml version<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span>\<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>1.0<span class="pl-cce" style="box-sizing: border-box;">\"</span>?></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><catalog></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"> <book id=<span class="pl-cce" style="box-sizing: border-box;">\"</span>bk101<span class="pl-cce" style="box-sizing: border-box;">\"</span> empty=<span class="pl-cce" style="box-sizing: border-box;">\"\"</span>></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"> <author><span class="pl-pse" style="box-sizing: border-box;">\(</span><span class="pl-s1" style="box-sizing: border-box; color: rgb(51, 51, 51);">author</span><span class="pl-pse" style="box-sizing: border-box;">)</span></author></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"> </book></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"></catalog></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);">END</span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);">print(<<<span class="pl-pds" style="box-sizing: border-box;">"</span></span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">---</span><span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span> + <<e<span class="pl-pds" style="box-sizing: border-box;">"</span></span>END<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>)</span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);">It was a dark and stormy </span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pse" style="box-sizing: border-box;">\(</span><span class="pl-s1" style="box-sizing: border-box; color: rgb(51, 51, 51);">timeOfDay</span><span class="pl-pse" style="box-sizing: border-box;">)</span> when </span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);">---</span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);">the Swift core team invented </span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);">the <span class="pl-pse" style="box-sizing: border-box;">\(</span><span class="pl-s1" style="box-sizing: border-box; color: rgb(51, 51, 51);">interpolation</span><span class="pl-pse" style="box-sizing: border-box;">)</span> syntax.</span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);">END</span></pre></div><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">A more Swift-style syntax might use a <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">#</code> function:</p><div class="highlight highlight-source-swift" style="box-sizing: border-box; margin-bottom: 16px;"><pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; margin-top: 0px; margin-bottom: 0px; line-height: 1.45; padding: 16px; overflow: auto; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-wrap: normal; word-break: normal;" class=""><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">print</span>(#to(<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>END<span class="pl-pds" style="box-sizing: border-box;">"</span></span>))
<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);"><</span>?xml version<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span>\<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>1.0<span class="pl-cce" style="box-sizing: border-box;">\"</span>?></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><catalog></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"> <book id=<span class="pl-cce" style="box-sizing: border-box;">\"</span>bk101<span class="pl-cce" style="box-sizing: border-box;">\"</span> empty=<span class="pl-cce" style="box-sizing: border-box;">\"\"</span>></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"> <author><span class="pl-pse" style="box-sizing: border-box;">\(</span><span class="pl-s1" style="box-sizing: border-box; color: rgb(51, 51, 51);">author</span><span class="pl-pse" style="box-sizing: border-box;">)</span></author></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"> </book></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"></catalog></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);">END</span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);">print(#to(<span class="pl-pds" style="box-sizing: border-box;">"</span></span><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">---</span><span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>) + e#to(<span class="pl-pds" style="box-sizing: border-box;">"</span></span>END<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span>))</span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);">It was a dark and stormy </span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pse" style="box-sizing: border-box;">\(</span><span class="pl-s1" style="box-sizing: border-box; color: rgb(51, 51, 51);">timeOfDay</span><span class="pl-pse" style="box-sizing: border-box;">)</span> when </span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);">---</span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);">the Swift core team invented </span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);">the <span class="pl-pse" style="box-sizing: border-box;">\(</span><span class="pl-s1" style="box-sizing: border-box; color: rgb(51, 51, 51);">interpolation</span><span class="pl-pse" style="box-sizing: border-box;">)</span> syntax.</span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);">END</span></pre></div><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">Or we might even borrow Python's <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">"""</code> delimiter, creating an unholy union of the two languages:</p><div class="highlight highlight-source-swift" style="box-sizing: border-box; margin-bottom: 16px;"><pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; margin-top: 0px; margin-bottom: 0px; line-height: 1.45; padding: 16px; overflow: auto; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-wrap: normal; word-break: normal;" class=""><span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">print</span>(<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span>)</span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><?xml version=<span class="pl-cce" style="box-sizing: border-box;">\"</span>1.0<span class="pl-cce" style="box-sizing: border-box;">\"</span>?></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><catalog></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"> <book id=<span class="pl-cce" style="box-sizing: border-box;">\"</span>bk101<span class="pl-cce" style="box-sizing: border-box;">\"</span> empty=<span class="pl-cce" style="box-sizing: border-box;">\"\"</span>></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"> <author><span class="pl-pse" style="box-sizing: border-box;">\(</span><span class="pl-s1" style="box-sizing: border-box; color: rgb(51, 51, 51);">author</span><span class="pl-pse" style="box-sizing: border-box;">)</span></author></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"> </book></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"></catalog></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>
<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">print</span>(<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span> + e<span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>)
It was a dark and stormy
\(timeOfDay) when
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);">the Swift core team invented </span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);">the <span class="pl-pse" style="box-sizing: border-box;">\(</span><span class="pl-s1" style="box-sizing: border-box; color: rgb(51, 51, 51);">interpolation</span><span class="pl-pse" style="box-sizing: border-box;">)</span> syntax.</span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span><span class="pl-pds" style="box-sizing: border-box;">"</span></span></pre></div><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">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.</p><h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em;" class=""><a id="user-content-other-potential-modifier-features" class="anchor" href="https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#other-potential-modifier-features" aria-hidden="true" style="box-sizing: border-box; background-color: transparent; -webkit-text-decoration-skip: objects; color: rgb(64, 120, 192); text-decoration: none; display: inline-block; padding-right: 2px; margin-left: -18px; line-height: 1.2;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Other potential modifier features</h3><ul style="box-sizing: border-box; padding-left: 2em; margin-top: 0px; margin-bottom: 16px;" class=""><li style="box-sizing: border-box;" class=""><p style="box-sizing: border-box; margin-top: 16px; margin-bottom: 16px;" class=""><span style="box-sizing: border-box;" class="">Whitespace normalization</span>: Changes all runs of whitespace in the literal to single space characters; this would allow you to use multiline strings and other spacing purely to improve code formatting.</p><pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; margin-top: 0px; margin-bottom: 16px; line-height: 1.45; padding: 16px; overflow: auto; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-wrap: normal;" class=""><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-break: normal; border: 0px; display: inline; line-height: inherit; word-wrap: normal;" class="">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."
</code></pre></li><li style="box-sizing: border-box;" class=""><p style="box-sizing: border-box; margin-top: 16px; margin-bottom: 16px;" class=""><span style="box-sizing: border-box;" class="">Localization</span>: Passes the string through Foundation's localization APIs; interpolations would be represented as format strings.</p><pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; margin-top: 0px; margin-bottom: 16px; line-height: 1.45; padding: 16px; overflow: auto; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-wrap: normal;" class=""><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-break: normal; border: 0px; display: inline; line-height: inherit; word-wrap: normal;" class="">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."
</code></pre></li><li style="box-sizing: border-box;" class=""><p style="box-sizing: border-box; margin-top: 16px; margin-bottom: 16px;" class=""><span style="box-sizing: border-box;" class="">Comments</span>: Embedding comments in string literals which were not included in their contents might be useful for literals containing regular expressions or other code.</p></li></ul><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">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.</p><h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em;" class=""><a id="user-content-a-note-on-regular-expressions" class="anchor" href="https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#a-note-on-regular-expressions" aria-hidden="true" style="box-sizing: border-box; background-color: transparent; -webkit-text-decoration-skip: objects; color: rgb(64, 120, 192); text-decoration: none; display: inline-block; padding-right: 2px; margin-left: -18px; line-height: 1.2;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>A note on regular expressions</h3><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">Members of the core team are interested in regular expressions, but they don't want to just build a literal that wraps PCRE or ICU; 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.</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">In the meantime, the <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">e</code> modifier and perhaps other string literal modifiers will make it easier to specify regular expressions in string literals for use with <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">NSRegularExpression</code> and other libraries accessible from Swift.</p><h2 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.225; font-size: 1.75em; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238);" class=""><a id="user-content-alternatives-considered" class="anchor" href="https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#alternatives-considered" aria-hidden="true" style="box-sizing: border-box; background-color: transparent; -webkit-text-decoration-skip: objects; color: rgb(64, 120, 192); text-decoration: none; display: inline-block; padding-right: 2px; margin-left: -18px; line-height: 1;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Alternatives considered</h2><h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em;" class=""><a id="user-content-dont-require-a-continuation-quote" class="anchor" href="https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#dont-require-a-continuation-quote" aria-hidden="true" style="box-sizing: border-box; background-color: transparent; -webkit-text-decoration-skip: objects; color: rgb(64, 120, 192); text-decoration: none; display: inline-block; padding-right: 2px; margin-left: -18px; line-height: 1.2;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Don't require a continuation quote</h3><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">The main alternative is to not require a continuation quote at the beginning of each subsequent line, and simply extend the string literal from the starting quote to the ending quote, including all newlines between them. For example:</p><div class="highlight highlight-source-swift" style="box-sizing: border-box; margin-bottom: 16px;"><pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; margin-top: 0px; margin-bottom: 0px; line-height: 1.45; padding: 16px; overflow: auto; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-wrap: normal; word-break: normal;" class=""><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">let</span> xml <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">=</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box;">"</span><?xml version=<span class="pl-cce" style="box-sizing: border-box;">\"</span>1.0<span class="pl-cce" style="box-sizing: border-box;">\"</span>?></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><catalog></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"> <book id=<span class="pl-cce" style="box-sizing: border-box;">\"</span>bk101<span class="pl-cce" style="box-sizing: border-box;">\"</span> empty=<span class="pl-cce" style="box-sizing: border-box;">\"\"</span>></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"> <author><span class="pl-pse" style="box-sizing: border-box;">\(</span><span class="pl-s1" style="box-sizing: border-box; color: rgb(51, 51, 51);">author</span><span class="pl-pse" style="box-sizing: border-box;">)</span></author></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"> </book></span>
<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"></catalog><span class="pl-pds" style="box-sizing: border-box;">"</span></span></pre></div><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">This alternative is extensively discussed in the "Rationale" section above.</p><h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em;" class=""><a id="user-content-use-verbatim-strings-or-heredocs-instead" class="anchor" href="https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#use-verbatim-strings-or-heredocs-instead" aria-hidden="true" style="box-sizing: border-box; background-color: transparent; -webkit-text-decoration-skip: objects; color: rgb(64, 120, 192); text-decoration: none; display: inline-block; padding-right: 2px; margin-left: -18px; line-height: 1.2;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Use verbatim strings or heredocs instead</h3><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">While these constructs have their place, a feature with lighter syntactic weight, better code formatting, and improved diagnostics is more appropriate for shorter multiline strings. See "An aside: Small and large multiline strings" above.</p><h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em;" class=""><a id="user-content-introduce-verbatim-strings-or-heredocs-first-or-at-the-same-time" class="anchor" href="https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#introduce-verbatim-strings-or-heredocs-first-or-at-the-same-time" aria-hidden="true" style="box-sizing: border-box; background-color: transparent; -webkit-text-decoration-skip: objects; color: rgb(64, 120, 192); text-decoration: none; display: inline-block; padding-right: 2px; margin-left: -18px; line-height: 1.2;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Introduce verbatim strings or heredocs first, or at the same time</h3><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">Verbatim strings could probably be implemented relatively easily, but heredocs are probably too complex for the Swift 3 timeframe. We don't want to choose between these two approaches merely on the basis that one can be implemented sooner.</p><h3 style="box-sizing: border-box; margin-top: 1em; margin-bottom: 16px; line-height: 1.43; font-size: 1.5em;" class=""><a id="user-content-dont-require-the-end-quote" class="anchor" href="https://gist.github.com/brentdax/c580bae68990b160645c030b2d0d1a8f#dont-require-the-end-quote" aria-hidden="true" style="box-sizing: border-box; background-color: transparent; -webkit-text-decoration-skip: objects; color: rgb(64, 120, 192); text-decoration: none; display: inline-block; padding-right: 2px; margin-left: -18px; line-height: 1.2;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M4 9h1v1h-1c-1.5 0-3-1.69-3-3.5s1.55-3.5 3-3.5h4c1.45 0 3 1.69 3 3.5 0 1.41-0.91 2.72-2 3.25v-1.16c0.58-0.45 1-1.27 1-2.09 0-1.28-1.02-2.5-2-2.5H4c-0.98 0-2 1.22-2 2.5s1 2.5 2 2.5z m9-3h-1v1h1c1 0 2 1.22 2 2.5s-1.02 2.5-2 2.5H9c-0.98 0-2-1.22-2-2.5 0-0.83 0.42-1.64 1-2.09v-1.16c-1.09 0.53-2 1.84-2 3.25 0 1.81 1.55 3.5 3 3.5h4c1.45 0 3-1.69 3-3.5s-1.5-3.5-3-3.5z"></path></svg></a>Don't require the end quote</h3><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">Since each line is marked with a continuation quote, in theory, the end quote is redundant; the string could simply end after the last line with a continuation quote.</p><pre style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; margin-top: 0px; margin-bottom: 16px; line-height: 1.45; padding: 16px; overflow: auto; background-color: rgb(247, 247, 247); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-wrap: normal;" class=""><code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; padding: 0px; margin: 0px; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-break: normal; border: 0px; display: inline; line-height: inherit; word-wrap: normal;" class="">// Something like:
let xml = M"<?xml version="1.0"?>
"<catalog>
" <book id="bk101" empty="">
" <author>\(author)</author>
" </book>
"</catalog>
</code></pre><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">Alternatively, the <code style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">M</code> modifier could be left out (which would require quotes on that line to be escaped), or a different character or character sequence could be used. There was a fair bit of bikeshedding on this; in some cases, a single post suggested several syntaxes with slightly different semantics (such as different escaping rules). Some marked the first and/or last line differently from the other lines. What they all have in common is that the beginning of each line is marked in some way, but the end is not, even at the end of the literal.</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">Because there is no end delimiter—only a start-of-line marker—these designs may not require you to escape quotes; thus, they could potentially obviate the need for an alternate delimiter feature as well. Depending on the design, however, many of them have issues:</p><ul style="box-sizing: border-box; padding-left: 2em; margin-top: 0px; margin-bottom: 16px;" class=""><li style="box-sizing: border-box;" class=""><p style="box-sizing: border-box; margin-top: 16px; margin-bottom: 16px;" class="">In most designs, it is possible to create a single-line string with the feature, but the resulting code tends to be ugly and awkward.</p></li><li style="box-sizing: border-box;" class=""><p style="box-sizing: border-box; margin-top: 16px; margin-bottom: 16px;" class="">If the last line is marked the same as the others and the user forgets the marker on a line, the compiler has no way to notice, except by diagnosing errors caused by treating a line of a string literal as code. Since some lines of string content will be valid code (such as blank lines or C-style comments), these mistakes may pass unnoticed.</p></li><li style="box-sizing: border-box;" class=""><p style="box-sizing: border-box; margin-top: 16px; margin-bottom: 16px;" class="">If the last line is marked the same as the others, then commenting out a line of a string literal, inserting a blank line in the middle of a string literal, or just in general inserting some sort of valid Swift code in the middle of a string literal would break the literal in half, once again potentially forming syntactically valid but incorrect Swift code.</p></li><li style="box-sizing: border-box;" class=""><p style="box-sizing: border-box; margin-top: 16px; margin-bottom: 16px;" class="">Generally, the more these constructs work to avoid the above problems, the uglier and less quote-like they end up looking, and the more complex they will be for the parser.</p></li></ul><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class="">Finally, all approaches share one fundamental issue.</p><div style="box-sizing: border-box; margin-top: 0px; margin-bottom: 0px !important;" class="">String literals are expressions, and so they ought to have a syntax which can be nested inside other expressions. Line-oriented features like these don't work well as expressions, because you normally place several expressions on a single line, nesting them inside one another. Thus, these features may be awkward to use in any but the simplest ways.</div></article></div></div></form></div><a name="comments" style="box-sizing: border-box; -webkit-text-decoration-skip: objects; color: rgb(64, 120, 192);" class=""></a><div class=" js-quote-selection-container gist-discussion-timeline discussion-timeline" style="box-sizing: border-box; position: relative; float: left; width: 980px;"><div class="js-socket-channel js-discussion" data-channel="brentdax/c580bae68990b160645c030b2d0d1a8f:marked-as-read:34913047" style="box-sizing: border-box;"><div id="partial-timeline-marker" class="js-socket-channel js-updatable-content js-timeline-marker" data-channel="brentdax/c580bae68990b160645c030b2d0d1a8f:gist:34913047" data-url="/brentdax/c580bae68990b160645c030b2d0d1a8f/show_partial?partial=gist%2Ftimeline_marker&since=1462416343" data-last-modified="Thu, 05 May 2016 02:45:43 GMT" style="box-sizing: border-box; color: rgb(51, 51, 51); font-family: Helvetica, arial, nimbussansl, liberationsans, freesans, clean, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 13px;"></div><div class="discussion-timeline-actions" style="box-sizing: border-box; background-color: rgb(255, 255, 255); border-top-width: 2px; border-top-style: solid; border-top-color: rgb(243, 243, 243); color: rgb(51, 51, 51); font-family: Helvetica, arial, nimbussansl, liberationsans, freesans, clean, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 13px;"><div class="timeline-comment-wrapper timeline-new-comment js-comment-container" style="box-sizing: border-box; position: relative; padding-left: 64px; margin-top: 15px; margin-bottom: 0px; border-top-width: 2px; border-top-style: solid; border-top-color: rgb(255, 255, 255); border-bottom-width: 2px; border-bottom-style: solid; border-bottom-color: rgb(255, 255, 255); max-width: inherit;"><a href="https://gist.github.com/brentdax" style="box-sizing: border-box; background-color: transparent; -webkit-text-decoration-skip: objects; color: rgb(64, 120, 192); text-decoration: none;" class=""></a></div></div></div></div><br class=""><div class="">-- <br class="">Brent Royal-Gordon<br class="">Architechies<br class=""></div><br class=""></div></body></html>