<div dir="ltr">On Tue, Apr 11, 2017 at 7:50 PM, Xiaodi Wu <span dir="ltr">&lt;<a href="mailto:xiaodi.wu@gmail.com" target="_blank">xiaodi.wu@gmail.com</a>&gt;</span> wrote:<br><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div class="m_6294085059502222686h5">On Tue, Apr 11, 2017 at 7:32 PM, Brent Royal-Gordon via swift-evolution <span dir="ltr">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;</span> wrote:<br></div></div><div class="gmail_extra"><div class="gmail_quote"><div><div class="m_6294085059502222686h5"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><br><div><span><blockquote type="cite"><div>On Apr 11, 2017, at 8:08 AM, Adrian Zubarev via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:</div><br class="m_6294085059502222686m_4625566802985836238m_869333541663561668Apple-interchange-newline"><div><div class="m_6294085059502222686m_4625566802985836238m_869333541663561668bloop_markdown" style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(254,254,254)"><p style="margin:15px 0px">That’s also the example that kept me thinking for a while.</p><hr style="height:0.2em;border:0px;color:rgb(204,204,204);background-color:rgb(204,204,204);display:inherit"><p style="margin:15px 0px">Overall the proposal is a great compromise to some issues I had with the first version. However I have a few more questions:</p><ul style="margin:15px 0px"><li style="margin:15px 0px">Why can’t we make it consistent and let the compiler add a new line after the starting delimiter.</li></ul><pre style="margin:15px 0px;font-family:Menlo,Consolas,&#39;Liberation Mono&#39;,Courier,monospace;font-size:10pt;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;background-color:rgb(248,248,248);color:inherit;border:1px solid rgb(204,204,204);overflow:auto;padding:4px 8px;word-break:normal;word-wrap:normal"><code class="m_6294085059502222686m_4625566802985836238m_869333541663561668swift" style="font-family:Menlo,Consolas,&#39;Liberation Mono&#39;,Courier,monospace;font-size:10pt;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;background-color:rgb(248,248,248);color:inherit;border:0px;margin:0px;padding:0px;word-break:normal;word-wrap:normal">
let string = &quot;&quot;&quot;↵
    Swift↵
    &quot;&quot;&quot;

// result
↵Swift↵
</code></pre><p style="margin:15px 0px">If one would would the behavior from the proposal it’s really easy to add a backslash after the starting delimiter.</p><pre style="margin:15px 0px;font-family:Menlo,Consolas,&#39;Liberation Mono&#39;,Courier,monospace;font-size:10pt;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;background-color:rgb(248,248,248);color:inherit;border:1px solid rgb(204,204,204);overflow:auto;padding:4px 8px;word-break:normal;word-wrap:normal"><code class="m_6294085059502222686m_4625566802985836238m_869333541663561668swift" style="font-family:Menlo,Consolas,&#39;Liberation Mono&#39;,Courier,monospace;font-size:10pt;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;background-color:rgb(248,248,248);color:inherit;border:0px;margin:0px;padding:0px;word-break:normal;word-wrap:normal">
let string = &quot;&quot;&quot;\↵
    Swift\↵
    &quot;&quot;&quot;

// result
Swift
</code></pre><p style="margin:15px 0px">This would be consistent and less confusing to learn.</p></div></div></blockquote></span>That would mean that code like this:</div><div><br></div><div><span class="m_6294085059502222686m_4625566802985836238m_869333541663561668Apple-tab-span" style="white-space:pre-wrap">        </span>print(&quot;&quot;&quot;</div><div><span class="m_6294085059502222686m_4625566802985836238m_869333541663561668Apple-tab-span" style="white-space:pre-wrap">                </span>A whole bunch of </div><div><span class="m_6294085059502222686m_4625566802985836238m_869333541663561668Apple-tab-span" style="white-space:pre-wrap">                </span>multiline text</div><div><span class="m_6294085059502222686m_4625566802985836238m_869333541663561668Apple-tab-span" style="white-space:pre-wrap">                </span>&quot;&quot;&quot;)</div><div><div><span class="m_6294085059502222686m_4625566802985836238m_869333541663561668Apple-tab-span" style="white-space:pre-wrap">        </span>print(&quot;&quot;&quot;</div><div><span class="m_6294085059502222686m_4625566802985836238m_869333541663561668Apple-tab-span" style="white-space:pre-wrap">                </span>A whole bunch more </div><div><span class="m_6294085059502222686m_4625566802985836238m_869333541663561668Apple-tab-span" style="white-space:pre-wrap">                </span>multiline text</div><div><span class="m_6294085059502222686m_4625566802985836238m_869333541663561668Apple-tab-span" style="white-space:pre-wrap">                </span>&quot;&quot;&quot;)</div><div><br></div><div>Will print (with - to indicate blank lines):</div><div><br></div><div><span class="m_6294085059502222686m_4625566802985836238m_869333541663561668Apple-tab-span" style="white-space:pre-wrap">        </span>-</div><div><span class="m_6294085059502222686m_4625566802985836238m_869333541663561668Apple-tab-span" style="white-space:pre-wrap">        </span>A whole bunch of</div><div><span class="m_6294085059502222686m_4625566802985836238m_869333541663561668Apple-tab-span" style="white-space:pre-wrap">        </span>multiline text</div><div><span class="m_6294085059502222686m_4625566802985836238m_869333541663561668Apple-tab-span" style="white-space:pre-wrap">        </span>-</div><div><span class="m_6294085059502222686m_4625566802985836238m_869333541663561668Apple-tab-span" style="white-space:pre-wrap">        </span>-</div><div><span class="m_6294085059502222686m_4625566802985836238m_869333541663561668Apple-tab-span" style="white-space:pre-wrap">        </span>A whole bunch more</div><div><span class="m_6294085059502222686m_4625566802985836238m_869333541663561668Apple-tab-span" style="white-space:pre-wrap">        </span>multiline text</div><div><span class="m_6294085059502222686m_4625566802985836238m_869333541663561668Apple-tab-span" style="white-space:pre-wrap">        </span>-</div><div><br></div><div>This is, to a first approximation, never what you actually want the computer to do.</div></div></div></blockquote><div><br></div></div></div><div>Brent, excellent job revising the proposal text. My question for you and the other authors is the other way around: what is the rationale behind only stripping the leading newline and not the trailing newline? While in many cases a trailing newline is not harmful or even beneficial, if you trim the one, wouldn&#39;t it make sense to trim the other? Wouldn&#39;t it make the rules easier to explain to users too? For instance:</div><div><br></div><div>&#39;&#39;&#39;</div><div>Hello, world!</div><div>&#39;&#39;&#39;</div><div><br></div><div>could instead be a one-line string &quot;Hello, world!&quot;</div><div><br></div><div>And those who need the trailing newline can trivially insist on it:</div><div><br></div><div>&#39;&#39;&#39;</div><div>Hello, world!</div><div><br></div><div>&#39;&#39;&#39;</div></div></div></div></blockquote><div><br></div><div>I should add, the motivation for proposing this revision to the rules is that it would make it easy for a user to make use of the de-indenting feature of the trailing &#39;&#39;&#39; without opting into a trailing newline by default.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span><div style="word-wrap:break-word"><div><span><blockquote type="cite"><div><div class="m_6294085059502222686m_4625566802985836238m_869333541663561668bloop_markdown" style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(254,254,254)"><ul style="margin:15px 0px"><li style="margin:15px 0px">Can’t we make the indent algorithm work like this instead?</li></ul><pre style="margin:15px 0px;font-family:Menlo,Consolas,&#39;Liberation Mono&#39;,Courier,monospace;font-size:10pt;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;background-color:rgb(248,248,248);color:inherit;border:1px solid rgb(204,204,204);overflow:auto;padding:4px 8px;word-break:normal;word-wrap:normal"><code style="font-family:Menlo,Consolas,&#39;Liberation Mono&#39;,Courier,monospace;font-size:10pt;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;background-color:rgb(248,248,248);color:inherit;border:0px;margin:0px;padding:0px;word-break:normal;word-wrap:normal">let string = &quot;&quot;&quot;\↵
····&lt;tag&gt;↵
······content text↵
····&lt;/tag&gt;&quot;&quot;&quot; // Indent starts with the first non space character

// result

&lt;tag&gt;↵
··content text↵
&lt;/tag&gt;
</code></pre><p style="margin:15px 0px">The line where the closing delimiter is trims all space chapters and the indent for the whole multi-line string is starting at the point where the first non-space chapters is in that line.</p></div></div></blockquote></span><div>We could; I discuss that briefly in the very last section, on alternatives to the indentation stripping we specify:</div><div><br></div><div><div><span class="m_6294085059502222686m_4625566802985836238m_869333541663561668Apple-tab-span" style="white-space:pre-wrap">        </span>• Stripping indentation to match the depth of the least indented line: Instead of removing indentation to match the end delimiter, you remove indentation to match the least indented line of the string itself. The issue here is that, if all lines in a string should be indented, you can&#39;t use indentation stripping. Ruby 2.3 does this with its heredocs, and Python&#39;s dedent function also implements this behavior.<br><br></div>That doesn&#39;t quite capture the entire breadth of the problem with this algorithm, though. What you&#39;d like to do is say, &quot;all of these lines are indented four columns, so we should remove four columns of indentation from each line&quot;. But you don&#39;t have columns; you have tabs and spaces, and they&#39;re incomparable because the compiler can&#39;t know what tab stops you set. So we&#39;d end up calculating a common prefix of whitespace for all lines and removing that. But that means, when someone mixes tabs and spaces accidentally, you end up stripping an amount of indentation that is unrelated to anything visible in your code. We could perhaps emit a warning in some suspicious circumstances (like &quot;every line has whitespace just past the end of indentation, but some use tabs and others use spaces&quot;), but if we do, we can&#39;t know which one is supposed to be correct. With the proposed design, we know what&#39;s correct—the last line—and any deviation from it can be flagged *at the particular line which doesn&#39;t match our expectation*.</div><div><br></div><div>Even without the tabs and spaces issue, consider the case where you accidentally don&#39;t indent a line far enough. With your algorithm, that&#39;s indistinguishable from wanting the other lines to be indented more than that one, so we generate a result you don&#39;t want and we don&#39;t (can&#39;t!) emit a warning to point out the mistake. With the proposed algorithm, we can notice there&#39;s an error and point to the line at fault.</div><div><br></div><div>Having the closing delimiter always be on its own line and using it to decide how much whitespace to strip is better because it gives the compiler a firm baseline to work from. That means it can tell you what&#39;s wrong and where, instead of doing the dumb computer thing and computing a result that&#39;s technically correct but useless.</div><span><blockquote type="cite"><div><div class="m_6294085059502222686m_4625566802985836238m_869333541663561668bloop_markdown" style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(254,254,254)"><p style="margin:15px 0px">PS: If we’d get this feature in Swift, it would be nice if Xcode and other IDEs which supports Swift could show space characters that are inside a string literal (not other space character &lt;- which is already supported), so it would be easier to tell what’s part of the string and what is not.</p></div></div></blockquote></span>That would be very nice indeed. The prototype&#39;s tokenizer simply concatenates together and computes the string literal&#39;s contents after whitespace stripping, but in principle, I think it could probably preserve enough information to tell SourceKit where the indentation ends and the literal content begins. (The prototype is John&#39;s department, though, not mine.) Xcode would then have to do something with that information, though, and swift-evolution can&#39;t make the Xcode team do so. But I&#39;d love to see a faint reddish background behind tripled string literal content or a vertical line at the indentation boundary.</div><div><br></div><div>In the meantime, this design *does* provide an unambiguous indicator of how much whitespace will be trimmed: however much is to the left of the closing delimiter. You just have to imagine the line extending upwards from there. I think that&#39;s an important thing to have.</div><span class="m_6294085059502222686m_4625566802985836238HOEnZb"><font color="#888888"><br><div>
<span class="m_6294085059502222686m_4625566802985836238m_869333541663561668Apple-style-span" style="border-collapse:separate;font-variant-ligatures:normal;font-variant-east-asian:normal;line-height:normal;border-spacing:0px"><div><div style="font-size:12px">-- </div><div style="font-size:12px">Brent Royal-Gordon</div><div style="font-size:12px">Architechies</div></div></span>

</div>
<br></font></span></div><br></span><span>______________________________<wbr>_________________<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" rel="noreferrer" target="_blank">https://lists.swift.org/mailma<wbr>n/listinfo/swift-evolution</a><br>
<br></span></blockquote></div><br></div></div>
</blockquote></div><br></div></div>