<div dir="ltr">This example will break easily when tabs are used for indentation or when using refactoring tools to rename the variable:<div><br></div><div><div style="font-size:12.8px"><font face="monospace, monospace">let text = """ </font></div><div style="font-size:12.8px"><font face="monospace, monospace"> This is ok.</font></div><div style="font-size:12.8px"><font face="monospace, monospace"> </font></div><div style="font-size:12.8px"><font face="monospace, monospace"> """</font></div></div><div style="font-size:12.8px"><span style="font-family:Menlo"><br></span></div>Rather I'd suggest that when there is no newline before the opening triple-quote then the indentation is ignored completely, like in the example from Drew Crawford:<div><br></div><div><div><font face="monospace, monospace">let sampleJSON = """</font></div><div><font face="monospace, monospace">{</font></div><div><font face="monospace, monospace"> "foo": "bar",</font></div><div><font face="monospace, monospace"> "baz": "bap\nbap"</font></div><div><font face="monospace, monospace">}</font></div><div><font face="monospace, monospace">"""</font></div><div><br></div><div>This is great for cases where you don't need to care about indentation or where you want to copy&paste something without re-indenting it.</div><div>It also works fine no matter if the developer uses tabs or spaces for indentation.</div></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Dec 11, 2015 at 10:26 AM, David Owens II via swift-evolution <span dir="ltr"><<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div>I think I’d rather treat the multiline literal as a fenced block.</div><div><br></div><div><font face="Menlo">let text =</font></div><div><font face="Menlo"> ""</font><span style="font-family:Menlo">"</span></div><div><font face="Menlo"> The position of the first </font><span style="font-family:Menlo">"</span><font face="Menlo"> is where the indentation is considered the left-edge.</font></div><div><font face="Menlo"> </font></div><div><font face="Menlo"> This line is indented four spaces.</font></div><div><font face="Menlo"><br></font></div><div><font face="Menlo"> </font></div><div><font face="Menlo"><br></font></div><div><font face="Menlo"><br></font></div><div><font face="Menlo"> If I want a newline at the end of the string, I simply put one.</font></div><div><font face="Menlo"><br></font></div><div><font face="Menlo"> </font><span style="font-family:Menlo">"</span><span style="font-family:Menlo">"</span><span style="font-family:Menlo">"</span></div><div><br></div><div>This creates very easy rules to understand:</div><div><br></div><div><ol><li>The position of the opening <font face="Menlo">""</font><span style="font-family:Menlo">"</span> dictates the left-edge for indentation purposes.</li><li>It’s invalid to have any text on the lines that contain the start and stop tokens: <font face="Menlo">""</font><span style="font-family:Menlo">"</span></li><li>The start and stop tokens must be left-edge aligned.</li><li>Text cannot be in a column that preceding the column the tokens start on, unless it is only whitespace.</li></ol><div><br></div></div><div>More examples:</div><div><br></div><div><div><font face="Menlo">let text =</font></div><div><font face="Menlo"> </font><span style="font-family:Menlo">"</span><span style="font-family:Menlo">"</span><span style="font-family:Menlo">"</span><font face="Menlo"> Invalid: This is not allowed.</font></div><div><font face="Menlo"> </font><span style="font-family:Menlo">"</span><span style="font-family:Menlo">"</span><span style="font-family:Menlo">"</span></div></div><div><span style="font-family:Menlo"><br></span></div><div><div><font face="Menlo">let text = </font><span style="font-family:Menlo">"</span><span style="font-family:Menlo">"</span><span style="font-family:Menlo">"</span><font face="Menlo"> Invalid; edges are not aligned.</font></div><div><span style="font-family:Menlo"> </span></div><div><font face="Menlo"> </font><span style="font-family:Menlo">"</span><span style="font-family:Menlo">"</span><span style="font-family:Menlo">"</span></div></div><div><br></div><div><div><font face="Menlo">let text = </font><span style="font-family:Menlo">"</span><span style="font-family:Menlo">"</span><span style="font-family:Menlo">"</span><font face="Menlo"> </font></div><div><font face="Menlo"> Invalid: Text cannot start before the </font><span style="font-family:Menlo">"</span><span style="font-family:Menlo">"</span><span style="font-family:Menlo">"</span><span style="font-family:Menlo"> tokens.</span></div><div><span style="font-family:Menlo"> </span></div><div><font face="Menlo"> </font><span style="font-family:Menlo">"</span><span style="font-family:Menlo">"</span><span style="font-family:Menlo">"</span></div></div><div><span style="font-family:Menlo"><br></span></div><div><div><div><font face="Menlo">let text = </font><span style="font-family:Menlo">"</span><span style="font-family:Menlo">"</span><span style="font-family:Menlo">"</span><font face="Menlo"> </font></div><div><font face="Menlo"> This is ok.</font></div><div><span style="font-family:Menlo"> </span></div><div><font face="Menlo"> </font><span style="font-family:Menlo">"</span><span style="font-family:Menlo">"</span><span style="font-family:Menlo">"</span></div></div></div><div><br></div><div><div><div><font face="Menlo">let text = </font><span style="font-family:Menlo">"</span><span style="font-family:Menlo">"</span><span style="font-family:Menlo">"</span><font face="Menlo"> </font></div><div><font face="Menlo"> Escaped characters are interpreted as normal: \n\n</font></div><div><font face="Menlo"> There will be two newlines above this string when rendered.</font></div><div><span style="font-family:Menlo"> </span></div><div><font face="Menlo"> </font><span style="font-family:Menlo">"</span><span style="font-family:Menlo">"</span><span style="font-family:Menlo">"</span></div></div></div><div><span style="font-family:Menlo"><br></span></div><div>-David</div><br><div><blockquote type="cite"><div><div class="h5"><div>On Dec 10, 2015, at 10:33 PM, Travis Tilley via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>> wrote:</div><br></div></div><div><div><div class="h5"><div dir="ltr"><div class="gmail_default" style="font-family:verdana,sans-serif">I had been operating on the assumption that a leading blank line would be stripped if present, since the syntax in code would look much cleaner, but a trailing line would not since it would likely be intentional. I guess that's another detail that would need to be fleshed out if we decide to go with triple quote syntax (which, at this point, isn't a given... chris lattner brings up some very good points that might require more involved, potentially heredoc-like, syntax to solve).</div><div class="gmail_default" style="font-family:verdana,sans-serif"><br></div><div class="gmail_default" style="font-family:verdana,sans-serif">Your fourth rule, however, I don't agree with at all. It should be obvious from where you place the final quotes whether or not the string includes a trailing newline. Just like in ruby, I believe in and value the principle of least surprize. </div><div class="gmail_default" style="font-family:verdana,sans-serif"><br></div><div class="gmail_default" style="font-family:verdana,sans-serif"><br></div><div class="gmail_default" style="font-family:verdana,sans-serif">- Travis Tilley</div><div class="gmail_default" style="font-family:verdana,sans-serif"><br></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Dec 11, 2015 at 1:04 AM, Jason Dusek <span dir="ltr"><<a href="mailto:jason.dusek@gmail.com" target="_blank">jason.dusek@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><span><p style="margin:1.2em 0px!important">On Thu, 10 Dec 2015 at 21:45, Travis Tilley via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>> wrote:</p><div style="margin:1.2em 0px!important"><br></div><div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div style="font-family:verdana,sans-serif">The ruby <<- heredoc syntax, unlike the << heredoc syntax, will strip indentation if necessary. Technically, it searches for the "least indented line" in the whole string, and removes exactly that amount from each line. So yes, the indentation problem -is- solved in ruby (though it might break entirely if you have empty lines, since the least indented line has no indentation).</div></div></blockquote><div><br></div></div><div style="margin:1.2em 0px!important"><br></div>
</span><p style="margin:1.2em 0px!important">To my mind, the rules should be:</p>
<ol style="margin:1.2em 0px;padding-left:2em">
<li style="margin:0.5em 0px">The indentation level is set from the least indented line that is not the first line and is not empty.</li>
<li style="margin:0.5em 0px">A leading empty line is removed.</li>
<li style="margin:0.5em 0px">The leading line, if there is any text in it, is not subject to de-indentation.</li>
</ol><p style="margin:1.2em 0px!important">I genuinely believe these three rules taken together address all the errors and infelicities to which triple quotes and HEREDOCs subject us. Here are some examples:</p>
<pre style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;font-size:1em;line-height:1.2em;margin:1.2em 0px"><code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);border-radius:3px;display:inline;background-color:rgb(248,248,248);white-space:pre-wrap;overflow:auto;border-radius:3px;border:1px solid rgb(204,204,204);padding:0.5em 0.7em;display:block!important;display:block;overflow-x:auto;padding:0.5em;color:rgb(51,51,51);background:rgb(248,248,248)">text = <span style="color:rgb(221,17,68)">"""
Some
Features
Are
Discussed
"""</span>
<span style="color:rgb(153,153,136);font-style:italic"># From (1): The indentation is taken from the third line below `text`, so it's 2.</span>
<span style="color:rgb(153,153,136);font-style:italic"># From (2): First line is: "\n" so it is removed.</span>
<span style="color:rgb(153,153,136);font-style:italic"># From (3): No effect.</span>
text = <span style="color:rgb(221,17,68)">""" Some
Features
Are
Discussed
"""</span>
<span style="color:rgb(153,153,136);font-style:italic"># From (1): The indentation is taken again from the line reading "Features". Here it is 10.</span>
<span style="color:rgb(153,153,136);font-style:italic"># From (2): No effect.</span>
<span style="color:rgb(153,153,136);font-style:italic"># From (3): The leading whitespace in ` Some` is preserved.</span>
</code></pre><p style="margin:1.2em 0px!important">Do you all think these rules pass muster?</p><p style="margin:1.2em 0px!important">A fourth rule — one which seems advisable but also less necessary than the others — is that a string constructed in this way always ends with a newline. It is a rule that perhaps leads to surprises and inconsistencies.</p><p style="margin:1.2em 0px!important">Best Regards,</p><p style="margin:1.2em 0px!important">Jason</p>
<div title="MDH:PGRpdiBjbGFzcz0iZ21haWxfcXVvdGUiPjxkaXYgZGlyPSJsdHIiPk9uIFRodSwgMTAgRGVjIDIw
MTUgYXQgMjE6NDUsIFRyYXZpcyBUaWxsZXkgdmlhIHN3aWZ0LWV2b2x1dGlvbiAmbHQ7PGEgaHJl
Zj0ibWFpbHRvOnN3aWZ0LWV2b2x1dGlvbkBzd2lmdC5vcmciIHRhcmdldD0iX2JsYW5rIj5zd2lm
dC1ldm9sdXRpb25Ac3dpZnQub3JnPC9hPiZndDsgd3JvdGU6PGJyPjwvZGl2PjxibG9ja3F1b3Rl
IGNsYXNzPSJnbWFpbF9xdW90ZSIgc3R5bGU9Im1hcmdpbjowIDAgMCAuOGV4O2JvcmRlci1sZWZ0
OjFweCAjY2NjIHNvbGlkO3BhZGRpbmctbGVmdDoxZXgiPjxkaXYgZGlyPSJsdHIiPjxkaXYgY2xh
c3M9ImdtYWlsX2RlZmF1bHQiIHN0eWxlPSJmb250LWZhbWlseTp2ZXJkYW5hLHNhbnMtc2VyaWYi
PlRoZSBydWJ5ICZsdDsmbHQ7LSBoZXJlZG9jIHN5bnRheCwgdW5saWtlIHRoZSAmbHQ7Jmx0OyBo
ZXJlZG9jIHN5bnRheCwgd2lsbCBzdHJpcCBpbmRlbnRhdGlvbiBpZiBuZWNlc3NhcnkuIFRlY2hu
aWNhbGx5LCBpdCBzZWFyY2hlcyBmb3IgdGhlICJsZWFzdCBpbmRlbnRlZCBsaW5lIiBpbiB0aGUg
d2hvbGUgc3RyaW5nLCBhbmQgcmVtb3ZlcyBleGFjdGx5IHRoYXQgYW1vdW50IGZyb20gZWFjaCBs
aW5lLiBTbyB5ZXMsIHRoZSBpbmRlbnRhdGlvbiBwcm9ibGVtIC1pcy0gc29sdmVkIGluIHJ1Ynkg
KHRob3VnaCBpdCBtaWdodCBicmVhayBlbnRpcmVseSBpZiB5b3UgaGF2ZSBlbXB0eSBsaW5lcywg
c2luY2UgdGhlIGxlYXN0IGluZGVudGVkIGxpbmUgaGFzIG5vIGluZGVudGF0aW9uKS48L2Rpdj48
L2Rpdj48L2Jsb2NrcXVvdGU+PGRpdj48YnI+PC9kaXY+PGRpdj5UbyBteSBtaW5kLCB0aGUgcnVs
ZXMgc2hvdWxkIGJlOjwvZGl2PjxkaXY+PGJyPjwvZGl2PjxkaXY+MS4gVGhlIGluZGVudGF0aW9u
IGxldmVsIGlzIHNldCBmcm9tIHRoZSBsZWFzdCBpbmRlbnRlZCBsaW5lIHRoYXQgaXMgbm90IHRo
ZSBmaXJzdCBsaW5lIGFuZCBpcyBub3QgZW1wdHkuPC9kaXY+PGRpdj4yLiBBIGxlYWRpbmcgZW1w
dHkgbGluZSBpcyByZW1vdmVkLjwvZGl2PjxkaXY+My4gVGhlIGxlYWRpbmcgbGluZSwgaWYgdGhl
cmUgaXMgYW55IHRleHQgaW4gaXQsIGlzIG5vdCBzdWJqZWN0IHRvIGRlLWluZGVudGF0aW9uLjxi
cj48YnI+SSBnZW51aW5lbHkgYmVsaWV2ZSB0aGVzZSB0aHJlZSBydWxlcyB0YWtlbiB0b2dldGhl
ciBhZGRyZXNzIGFsbCB0aGUgZXJyb3JzIGFuZCBpbmZlbGljaXRpZXMgdG8gd2hpY2ggdHJpcGxl
IHF1b3RlcyBhbmQgSEVSRURPQ3Mgc3ViamVjdCB1cy4gSGVyZSBhcmUgc29tZSBleGFtcGxlczo8
L2Rpdj48ZGl2Pjxicj48L2Rpdj48ZGl2PmBgYHB5dGhvbjwvZGl2PjxkaXY+dGV4dCA9ICIiIjwv
ZGl2PjxkaXY+Jm5ic3A7ICZuYnNwOyBTb21lPC9kaXY+PGRpdj48YnI+PC9kaXY+PGRpdj4mbmJz
cDsgRmVhdHVyZXM8L2Rpdj48ZGl2PiZuYnNwOyAmbmJzcDsgQXJlPC9kaXY+PGRpdj4mbmJzcDsg
Jm5ic3A7IERpc2N1c3NlZDwvZGl2PjxkaXY+IiIiPC9kaXY+PGRpdj4jIEZyb20gKDEpOiBUaGUg
aW5kZW50YXRpb24gaXMgdGFrZW4gZnJvbSB0aGUgdGhpcmQgbGluZSBiZWxvdyBgdGV4dGAsIHNv
IGl0J3MgMi48L2Rpdj48ZGl2PiMgRnJvbSAoMik6IEZpcnN0IGxpbmUgaXM6ICJcbiIgc28gaXQg
aXMgcmVtb3ZlZC48L2Rpdj48ZGl2PiMgRnJvbSAoMyk6IE5vIGVmZmVjdC48L2Rpdj48ZGl2Pjxi
cj48L2Rpdj48ZGl2PnRleHQgPSAiIiIgJm5ic3A7U29tZTwvZGl2PjxkaXY+PGJyPjwvZGl2Pjxk
aXY+Jm5ic3A7ICZuYnNwOyAmbmJzcDsgJm5ic3A7ICZuYnNwOyBGZWF0dXJlczwvZGl2PjxkaXY+
Jm5ic3A7ICZuYnNwOyAmbmJzcDsgJm5ic3A7ICZuYnNwOyAmbmJzcDsgQXJlPC9kaXY+PGRpdj4m
bmJzcDsgJm5ic3A7ICZuYnNwOyAmbmJzcDsgJm5ic3A7ICZuYnNwOyBEaXNjdXNzZWQ8L2Rpdj48
ZGl2PiIiIjwvZGl2PjxkaXY+IyBGcm9tICgxKTogVGhlIGluZGVudGF0aW9uIGlzIHRha2VuIGFn
YWluIGZyb20gdGhlIGxpbmUgcmVhZGluZyAiRmVhdHVyZXMiLiBIZXJlIGl0IGlzIDEwLjwvZGl2
PjxkaXY+IyBGcm9tICgyKTogTm8gZWZmZWN0LjwvZGl2PjxkaXY+IyBGcm9tICgzKTogVGhlIGxl
YWRpbmcgd2hpdGVzcGFjZSBpbiBgICZuYnNwO1NvbWVgIGlzIHByZXNlcnZlZC48L2Rpdj48ZGl2
PmBgYDwvZGl2PjxkaXY+PGJyPjwvZGl2PjxkaXY+RG8geW91IGFsbCB0aGluayB0aGVzZSBydWxl
cyBwYXNzIG11c3Rlcj88L2Rpdj48ZGl2Pjxicj48L2Rpdj48ZGl2PkEgZm91cnRoIHJ1bGUgLS0g
b25lIHdoaWNoIHNlZW1zIGFkdmlzYWJsZSBidXQgYWxzbyBsZXNzIG5lY2Vzc2FyeSB0aGFuIHRo
ZSBvdGhlcnMgLS0gaXMgdGhhdCBhIHN0cmluZyBjb25zdHJ1Y3RlZCBpbiB0aGlzIHdheSBhbHdh
eXMgZW5kcyB3aXRoIGEgbmV3bGluZS4gSXQgaXMgYSBydWxlIHRoYXQgcGVyaGFwcyBsZWFkcyB0
byBzdXJwcmlzZXMgYW5kIGluY29uc2lzdGVuY2llcy48L2Rpdj48ZGl2Pjxicj48L2Rpdj48ZGl2
PkJlc3QgUmVnYXJkcyw8L2Rpdj48ZGl2PiZuYnNwOyBKYXNvbjwvZGl2PjwvZGl2Pg==" style="min-height:0;width:0;max-height:0;max-width:0;overflow:hidden;font-size:0em;padding:0;margin:0"></div></div></div></blockquote></div>
</div></div>
</div></div><img src="https://u2002410.ct.sendgrid.net/wf/open?upn=nE9rxSXA5G4kxsTVkgv43pXkLx-2B36P-2BPNJufHeY0dgcG1a2qgARtkscK9573-2BVmscXS6V3ezn6lHY6jcm8BxOUPbfYDio5rcCppfEuXGkEsrzLR6GmLgb0I5Ec1vPMr3A4xzzM5-2BI-2B56EE40EW3gl9YjDl954m3x3PRsEwmEVdaSMDBSm-2FiK-2FFDFEIKBoekJfwjNYG74AQLFiOOhyHclaQ-3D-3D" alt="" width="1" height="1" border="0" style="min-height:1px!important;width:1px!important;border-width:0!important;margin-top:0!important;margin-bottom:0!important;margin-right:0!important;margin-left:0!important;padding-top:0!important;padding-bottom:0!important;padding-right:0!important;padding-left:0!important">
_______________________________________________<span class=""><br>swift-evolution mailing list<br><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br></span></div></blockquote></div><br>
<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=6ZGE61OxINd5lLe2xYh9Ku-2BXbixWNr2nvfzp2IB1sZgspp-2BS2jNtgwSoXsAd8DC5rzQOOLlGSbCSj9ObCVV-2BHuPb8RJC7Jv0WLi1ftAHIO8Bq0GWK8PBS3u4ABQRCGur0-2Bu2f9CJi1S914FJTCl0LCPcW2CPmE92cdPJZ6KgVDVScn-2Bh9SCgztyJYWQKcU0DwWCuM8LGyrJbzuOYA3J5oS-2FbywU11-2FfvpLmFqVlFoqY-3D" alt="" width="1" height="1" border="0" style="min-height:1px!important;width:1px!important;border-width:0!important;margin-top:0!important;margin-bottom:0!important;margin-right:0!important;margin-left:0!important;padding-top:0!important;padding-bottom:0!important;padding-right:0!important;padding-left:0!important">
</div>
<br>_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
<br></blockquote></div><br></div>