<html><head><style>
body {
        font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
        padding:1em;
        margin:auto;
        background:#fefefe;
}
h1, h2, h3, h4, h5, h6 {
        font-weight: bold;
}
h1 {
        color: #000000;
        font-size: 28pt;
}
h2 {
        border-bottom: 1px solid #CCCCCC;
        color: #000000;
        font-size: 24px;
}
h3 {
        font-size: 18px;
}
h4 {
        font-size: 16px;
}
h5 {
        font-size: 14px;
}
h6 {
        color: #777777;
        background-color: inherit;
        font-size: 14px;
}
hr {
        height: 0.2em;
        border: 0;
        color: #CCCCCC;
        background-color: #CCCCCC;
display: inherit;
}
p, blockquote, ul, ol, dl, li, table, pre {
        margin: 15px 0;
}
a, a:visited {
        color: #4183C4;
        background-color: inherit;
        text-decoration: none;
}
#message {
        border-radius: 6px;
        border: 1px solid #ccc;
        display:block;
        width:100%;
        height:60px;
        margin:6px 0px;
}
button, #ws {
        font-size: 12 pt;
        padding: 4px 6px;
        border-radius: 5px;
        border: 1px solid #bbb;
        background-color: #eee;
}
code, pre, #ws, #message {
        font-family: Monaco;
        font-size: 10pt;
        border-radius: 3px;
        background-color: #F8F8F8;
        color: inherit;
}
code {
        border: 1px solid #EAEAEA;
        margin: 0 2px;
        padding: 0 5px;
}
pre {
        border: 1px solid #CCCCCC;
        overflow: auto;
        padding: 4px 8px;
}
pre > code {
        border: 0;
        margin: 0;
        padding: 0;
}
#ws { background-color: #f8f8f8; }
.bloop_markdown table {
border-collapse: collapse;
font-family: Helvetica, arial, freesans, clean, sans-serif;
color: rgb(51, 51, 51);
font-size: 15px; line-height: 25px;
padding: 0; }
.bloop_markdown table tr {
border-top: 1px solid #cccccc;
background-color: white;
margin: 0;
padding: 0; }
.bloop_markdown table tr:nth-child(2n) {
background-color: #f8f8f8; }
.bloop_markdown table tr th {
font-weight: bold;
border: 1px solid #cccccc;
margin: 0;
padding: 6px 13px; }
.bloop_markdown table tr td {
border: 1px solid #cccccc;
margin: 0;
padding: 6px 13px; }
.bloop_markdown table tr th :first-child, table tr td :first-child {
margin-top: 0; }
.bloop_markdown table tr th :last-child, table tr td :last-child {
margin-bottom: 0; }
.bloop_markdown blockquote{
border-left: 4px solid #dddddd;
padding: 0 15px;
color: #777777; }
blockquote > :first-child {
margin-top: 0; }
blockquote > :last-child {
margin-bottom: 0; }
code, pre, #ws, #message {
word-break: normal;
word-wrap: normal;
}
hr {
display: inherit;
}
.bloop_markdown :first-child {
-webkit-margin-before: 0;
}
code, pre, #ws, #message {
font-family: Menlo, Consolas, Liberation Mono, Courier, monospace;
}
.send { color:#77bb77; }
.server { color:#7799bb; }
.error { color:#AA0000; }</style></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class="bloop_markdown"><p>Actually I’m fine with such a compromise. Such a model has everything we’ve asked for, it’s easy, it has both leading and trailing precision and implicit new lines where needed.</p>
<p></p></div><div class="bloop_original_html"><style>body{font-family:Helvetica,Arial;font-size:13px}</style><div id="bloop_customfont" style="font-family:Helvetica,Arial;font-size:13px; color: rgba(0,0,0,1.0); margin: 0px; line-height: auto;"><br></div> <br> <div id="bloop_sign_1491994049751838976" class="bloop_sign"><div style="font-family:helvetica,arial;font-size:13px">-- <br>Adrian Zubarev<br>Sent with Airmail</div></div> <br><p class="airmail_on">Am 12. April 2017 um 12:42:17, Vladimir.S via swift-evolution (<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>) schrieb:</p> <blockquote type="cite" class="clean_bq"><span><div><div></div><div>On 12.04.2017 13:16, Thorsten Seitz via swift-evolution wrote:<br>>> Am 12.04.2017 um 10:11 schrieb Adrian Zubarev via swift-evolution <br>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>>:<br>>><br>>> Great explanation thank you Brent. I’m convinced about the closing delimiter now. =)<br>>><br>>> -------------------------------------------------------------------------------------<br>>><br>>> If I understood correctly what Xiaodi Wu meant in his reply, then we could simplify <br>>> the whole multi-line string literal and also remove the need of disabling the <br>>> stripping algorithm.<br>>><br>>> We should ban these examples completely:<br>>><br>>> |"""Hello·world!"""|<br>>><br>> <br>> Being able to use ""“ for single line strings containing lots of " is useful in <br>> itself and explained in the motivational section of the proposal:<br>> "Tripled string literals can also do double duty as a syntax for handling short <br>> string literals with many internal quotation marks“<br>> <br>> -Thorsten<br><br>Yes, I also think the single line string can be very useful and we should not <br>disallow it.<br><br>But I agree that we should disallow multi-line cases when we have text on the same <br>line with leading or trailing """ because this complicates the mental modal and adds <br>confusion points.<br><br>I.e. I suggest to allow only two forms:<br>1. Single line: """this is "just" text""" (no line end will be inserted)<br>2. Multiline, where leading and trailing """ has no text after/before them and *all* <br>the text is in lines *between* triple quotes:<br>"""<br> first line<br> second line<br>"""<br><br>One can use backslash at the line end to emulate all other needed cases. Like:<br><br>"""<br> first line \<br> second line\<br>"""<br><br>will produce "first line second line"<br><br>> <br>>> |"""Hello↵ world!""" |<br>>> |"""Hello↵ world!↵ """ |<br>>> |"""↵ Hello↵ world!""" |<br>>><br>>> Instead an empty multi-line string literal would look like this:<br>>><br>>> |"""↵ """ |<br>>><br>>> To fix the above example you’d need to write it like this:<br>>><br>>> |"""↵ Hello·world!\↵ """ |<br>>> |"""↵ Hello↵ world!\↵ """ |<br>>><br>>> * Each line in between the delimiters would add implicit new lines if not<br>>> disabled by a backslash.<br>>> * The trailing precision is also handled by the backslash.<br>>> * The indent is handled by the closing delimiter.<br>>> * It’s easier to learn/teach.<br>>> * It’s easier to read, because most of the time the line where the starting<br>>> delimiter is, is filled with some other code.<br>>><br>>> |let myString = """↵ ⇥ ⇥ Hello↵ ⇥ ⇥ world!\↵ ⇥ ⇥ """ |<br>>><br>>> Now that would be a true multi-line string literal which needs at least two lines <br>>> of code. If you’d need a single line literal,|""|is the obvious pick.<br>>><br>>><br>>><br>>><br>>> -- <br>>> Adrian Zubarev<br>>> Sent with Airmail<br>>><br>>> Am 12. April 2017 um 02:32:33, Brent Royal-Gordon (brent@architechies.com <br>>> <mailto:brent@architechies.com>) schrieb:<br>>><br>>>><br>>>>> On Apr 11, 2017, at 8:08 AM, Adrian Zubarev via swift-evolution <br>>>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:<br>>>>><br>>>>> That’s also the example that kept me thinking for a while.<br>>>>><br>>>>> -------------------------------------------------------------------------------------<br>>>>><br>>>>> Overall the proposal is a great compromise to some issues I had with the first <br>>>>> version. However I have a few more questions:<br>>>>><br>>>>> * Why can’t we make it consistent and let the compiler add a new line after the<br>>>>> starting delimiter.<br>>>>><br>>>>> |
let string = """↵ Swift↵ """ // result ↵Swift↵ |<br>>>>><br>>>>> If one would would the behavior from the proposal it’s really easy to add a <br>>>>> backslash after the starting delimiter.<br>>>>><br>>>>> |
let string = """\↵ Swift\↵ """ // result Swift |<br>>>>><br>>>>> This would be consistent and less confusing to learn.<br>>>>><br>>>> That would mean that code like this:<br>>>><br>>>> print("""<br>>>> A whole bunch of<br>>>> multiline text<br>>>> """)<br>>>> print("""<br>>>> A whole bunch more<br>>>> multiline text<br>>>> """)<br>>>><br>>>> Will print (with - to indicate blank lines):<br>>>><br>>>> -<br>>>> A whole bunch of<br>>>> multiline text<br>>>> -<br>>>> -<br>>>> A whole bunch more<br>>>> multiline text<br>>>> -<br>>>><br>>>> This is, to a first approximation, never what you actually want the computer to do.<br>>>>><br>>>>> * Can’t we make the indent algorithm work like this instead?<br>>>>><br>>>>> |let string = """\↵ ····<tag>↵ ······content text↵ ····</tag>""" // Indent starts <br>>>>> with the first non space character // result <tag>↵ ··content text↵ </tag> |<br>>>>><br>>>>> The line where the closing delimiter is trims all space chapters and the indent <br>>>>> for the whole multi-line string is starting at the point where the first <br>>>>> non-space chapters is in that line.<br>>>>><br>>>> We could; I discuss that briefly in the very last section, on alternatives to the <br>>>> indentation stripping we specify:<br>>>><br>>>> • Stripping indentation to match the depth of the least indented line: Instead of <br>>>> removing indentation to match the end delimiter, you remove indentation to match <br>>>> the least indented line of the string itself. The issue here is that, if all lines <br>>>> in a string should be indented, you can't use indentation stripping. Ruby 2.3 does <br>>>> this with its heredocs, and Python's dedent function also implements this behavior.<br>>>><br>>>> That doesn't quite capture the entire breadth of the problem with this algorithm, <br>>>> though. What you'd like to do is say, "all of these lines are indented four <br>>>> columns, so we should remove four columns of indentation from each line". But you <br>>>> don't have columns; you have tabs and spaces, and they're incomparable because the <br>>>> compiler can't know what tab stops you set. So we'd end up calculating a common <br>>>> prefix of whitespace for all lines and removing that. But that means, when someone <br>>>> mixes tabs and spaces accidentally, you end up stripping an amount of indentation <br>>>> that is unrelated to anything visible in your code. We could perhaps emit a <br>>>> warning in some suspicious circumstances (like "every line has whitespace just <br>>>> past the end of indentation, but some use tabs and others use spaces"), but if we <br>>>> do, we can't know which one is supposed to be correct. With the proposed design, <br>>>> we know what's correct—the last line—and any deviation from it can be flagged *at <br>>>> the particular line which doesn't match our expectation*.<br>>>><br>>>> Even without the tabs and spaces issue, consider the case where you accidentally <br>>>> don't indent a line far enough. With your algorithm, that's indistinguishable from <br>>>> wanting the other lines to be indented more than that one, so we generate a result <br>>>> you don't want and we don't (can't!) emit a warning to point out the mistake. With <br>>>> the proposed algorithm, we can notice there's an error and point to the line at fault.<br>>>><br>>>> Having the closing delimiter always be on its own line and using it to decide how <br>>>> much whitespace to strip is better because it gives the compiler a firm baseline <br>>>> to work from. That means it can tell you what's wrong and where, instead of doing <br>>>> the dumb computer thing and computing a result that's technically correct but useless.<br>>>>><br>>>>> PS: If we’d get this feature in Swift, it would be nice if Xcode and other IDEs <br>>>>> which supports Swift could show space characters that are inside a string literal <br>>>>> (not other space character <- which is already supported), so it would be easier <br>>>>> to tell what’s part of the string and what is not.<br>>>>><br>>>> That would be very nice indeed. The prototype's tokenizer simply concatenates <br>>>> together and computes the string literal's contents after whitespace stripping, <br>>>> but in principle, I think it could probably preserve enough information to tell <br>>>> SourceKit where the indentation ends and the literal content begins. (The <br>>>> prototype is John's department, though, not mine.) Xcode would then have to do <br>>>> something with that information, though, and swift-evolution can't make the Xcode <br>>>> team do so. But I'd love to see a faint reddish background behind tripled string <br>>>> literal content or a vertical line at the indentation boundary.<br>>>><br>>>> In the meantime, this design *does* provide an unambiguous indicator of how much <br>>>> whitespace will be trimmed: however much is to the left of the closing delimiter. <br>>>> You just have to imagine the line extending upwards from there. I think that's an <br>>>> important thing to have.<br>>>><br>>>> -- <br>>>> Brent Royal-Gordon<br>>>> Architechies<br>>>><br>>><br>>> _______________________________________________<br>>> swift-evolution mailing list<br>>> swift-evolution@swift.org <mailto:swift-evolution@swift.org><br>>> https://lists.swift.org/mailman/listinfo/swift-evolution<br>> <br>> <br>> <br>> _______________________________________________<br>> swift-evolution mailing list<br>> swift-evolution@swift.org<br>> https://lists.swift.org/mailman/listinfo/swift-evolution<br>> <br>_______________________________________________<br>swift-evolution mailing list<br>swift-evolution@swift.org<br>https://lists.swift.org/mailman/listinfo/swift-evolution<br></div></div></span></blockquote></div><div class="bloop_markdown"><p></p></div></body></html>