<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">On Nov 24, 2018, at 11:39 PM, Cay Horstmann <<a href="mailto:cay.horstmann@sjsu.edu" class="">cay.horstmann@sjsu.edu</a>> wrote:<br class=""><div><blockquote type="cite" class=""><br class="Apple-interchange-newline"><div class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 16px; 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; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">I agree that it is inelegant that there is no good syntax for raw strings starting with a backtick. Some time ago (</span><a href="http://horstmann.com/unblog/2018-06-01" style="font-family: Helvetica; font-size: 16px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">http://horstmann.com/unblog/2018-06-01</a><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 16px; 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; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">), I suggested that an initial newline after the backticks could count as part of the raw string delimiter:</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 16px; 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; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 16px; 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; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 16px; 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; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">     String myNameInABox = ```</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 16px; 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; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 16px; 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; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">+-----+</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 16px; 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; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 16px; 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; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">| Cay |</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 16px; 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; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 16px; 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; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">+-----+```; // This string starts with +</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 16px; 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; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 16px; 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; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 16px; 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; -webkit-text-stroke-width: 0px; text-decoration: none; float: none; display: inline !important;" class="">Ok, maybe it's not brilliant, but it solves two problems: (1) how to format multiline strings that should be aligned, without having to strip out the initial newline (2) how to declare strings that start with a backtick.</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 16px; 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; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""></div></blockquote></div><br class=""><div class="">The basic reality here is that we are trying to keep the quotes as simple as possible,</div><div class="">while allowing them to quote anything at all, including their shorter siblings.</div><div class="">A close-quote can't both appear in a string and end that string for obvious reasons.</div><div class=""><br class=""></div><div class="">Result:  There must be an infinite set of close-quotes available, so that even if a</div><div class="">string has the first N-1 close-quotes inside it, it can be terminated with the Nth one.</div><div class="">This also implies there must be a corresponding infinite set of open-quotes.</div><div class="">(Opens and closes can be pairwise identical, as in the proposed feature.)</div><div class=""><br class=""></div><div class="">Next, we have the problem of designing a set of open quotes which can</div><div class="">be differentiated from each other before the string body proper is scanned.</div><div class="">(You have to determine the close-quote before scanning the string body.)</div><div class=""><br class=""></div><div class="">This really means that open-quotes must be self-delimiting, or else that</div><div class="">there are some substrings that are forbidden to follow at least some</div><div class="">open-quotes.  If an open-quote syntax is not fully self-delimiting, there</div><div class="">are two open-quotes Q, QR for which Q is a proper prefix of QR.  In this</div><div class="">case, a quoted string body cannot begin with R and be quoted with Q.</div><div class=""><br class=""></div><div class="">In the present case, we allow the open-quotes to be composed of an</div><div class="">alphabet of only one letter, the backtick, but allow any positive number</div><div class="">of them.  That's pretty good (and really, really simple) but it does have</div><div class="">the observed defect, that none of the open-quotes are self-delimiting,</div><div class="">because for any N>0, "`".times(N) is a proper prefix of the next open-quote,</div><div class="">"`".times(N+1).  Thus, for no open-quote (in the present scheme) can</div><div class="">the string body begin with backtick.</div><div class=""><br class=""></div><div class="">(There is a mirror-image problem with the end-quotes, if they are</div><div class="">not self-delimiting.  It must be possible, for any given string, to</div><div class="">choose an end-quote which (a) isn't in the string, and (b) when</div><div class="">appended to the string does not create an earlier instance of itself.</div><div class="">Again, having an alphabet of one character Q for the end-quotes</div><div class="">means that the string cannot end in Q.)</div><div class=""><br class=""></div><div class="">Can an infinite set of strings which are repetitions of a single character</div><div class="">be made self-delimiting?  Never, since any given member of that set</div><div class="">is the proper prefix of some longer member.</div><div class=""><br class=""></div><div class="">Making such a set self-delimiting is simple:  Add another character,</div><div class="">and allow it to be a terminating character for the open-quote.</div><div class="">Or, allow the open-quote to include an optional numeric count</div><div class="">that determines the length of the rest of the quote.  Or, allow</div><div class="">the open-quote to have arbitrary (quoted) substructure.</div><div class=""><br class=""></div><div class="">(And for each open-quote define a corresponding close-quote.</div><div class="">Then given a string, choose the shortest close-quote that does not</div><div class="">occur in the string, and which when appended to the string will</div><div class="">not create an earlier instance of itself.  Begin the quoted string</div><div class="">what that close-quote's open-quote.)</div><div class=""><br class=""></div><div class="">Supposing that Q is the main quote character and R is a helper</div><div class="">(or two or more) which helps size the end-quote.  Examples of</div><div class="">these three approaches would be:</div><div class=""><br class=""></div><div class="">  OQ1 = { Q.times(N) + R | N > 0 }</div><div class="">  OQ2 = { R + String.valueOf(N) + Q.times(N) | N > 0 }</div><div class="">  OQ3 = { Q + S + R | S in (Universe - R).star() }</div><div class=""><br class=""></div><div class="">Such schemes are more powerful, but much harder to describe than</div><div class="">what we have now:</div><div class=""><br class=""></div><div class="">  OQ0 = { Q.times(N) | N > 0, Q = \" }</div><div class=""><br class=""></div><div class="">Coming up with these schemes is simple.  Coming up with a scheme</div><div class="">that feels simple to use seems to be impossible.  Tuning and tweaking</div><div class="">these schemes is *NOT* a hill-climbing activity that ascends to better</div><div class="">and better solutions.  Creating self-delimiting string syntaxes is a</div><div class="">frustrating exercise in pushing the complexities and corner cases</div><div class="">into darker and darker holes.</div><div class=""><br class=""></div><div class="">We settled on OQ0 (alphabet of one character) because it is simple</div><div class="">and easy to understand.  We looked carefully at other OQ schemes</div><div class="">and did not find that their specification and learning complexity</div><div class="">was paid for by removing the practical complexity of encoding a</div><div class="">few odd-looking strings.  OQ1, etc., have their own sharp edges</div><div class="">which we think users will run into more often than they will run</div><div class="">into the sharp edges of OQ0.  Trying to "fix" OQ0 just makes it</div><div class="">messier, like rubbing your finger over that single speck of lint on the</div><div class="">lens of your new binoculars.</div><div class=""><br class=""></div><div class="">— John</div></body></html>