# Wrapping up the first two courses

Mon Apr 22 15:26:52 UTC 2019

```Current "strip incidentals" algorithm as captured in String::align (string-tapas branch)

public String align(int n) {
if (isEmpty()) {
return "";
}
long count = lines().count();
if (count == 1) {
return strip();
}
int outdent = lines().skip(1)
.filter(not(String::isBlank))
.mapToInt(String::indexOfNonWhitespace)
.min()
.orElse(0);
String last = lines().skip(count - 1).findFirst().orElse("");
boolean lastIsBlank = last.isBlank();
if (lastIsBlank) {
outdent = Integer.min(outdent, last.length());
}
return indentStream(lines(1, 1), n - outdent).map(s -> s.stripTrailing())
.collect(Collectors.joining("\n", "", lastIsBlank ? "\n" : ""));
}

1. if (isEmpty()) {
return "";
}

Empty strings returned as empty.

"""""" ==> ""

2. long count = lines().count();
if (count == 1) {
return strip();
}

Single line strings (no line terminators) are simply stripped.

"""  single line  """ ==> "single line"

3.  int outdent = lines().skip(1) ...

Ignoring first line, determine least number of leading whitespaces for all
non-blank lines.

String s = """
................line 1..
....................line 2.
""";  ==> 16

4. boolean lastIsBlank = last.isBlank();

Detect if last line is blank.

5. if (lastIsBlank) {
outdent = Integer.min(outdent, last.length());
}

If last line is blank, then check if it has least number of leading whitespaces.

String s = """
line 1
line 2
............""";  ==> 12

* Breaking down the return statement

6. Stream stream1 = lines(1, 1);

Break string into a stream of lines, stripping line terminators, stripping
first line if blank and stripping last line if blank.

................line 1..
....................line 2.

7. Stream stream2 = indentStream(stream1, n - outdent);

Remove indentation from each line in stream. It's possible that whitespace
gets added if n is larger than outdent.

....line 1..
........line 2.

8. Stream stream3 = stream2.map(s -> s.stripTrailing());

Remove incidental trailing whitespace.

....line 1
........line 2

9. return stream3.collect(Collectors.joining("\n", "", lastIsBlank ? "\n" : ""));

Join lines with \n and add a \n at the end if the last line was blank.

....line 1\n
........line 2\n

Options;

2. a) Single line strings would be just stripLeading, but should beconsistent
with multi-line and stripTrailing.

"""  single line  """ ==> "single line  "

b) We could do nothing for single line.

"""  single line  """ ==> "  single line  "

3. a) If we include open delimiter influence, the equivalent library method
can not duplicate the influence unless the user supplied the first line indentation.

5. a) If we omit close delimiter influence, only the content influences the
indentation.  Loss of control by the user.

String s = """
line 1
line 2
""";

==>

line 1\n
....line 2\n

6. a) Could strip all leading/trailing blank lines, but awkward to recover the
LOI. Not recommending.

String s = """

line 1
line 2

""";

==>

String s = "\n".repeat(3) + """
line 1
line 2
""" + "\n".repeat(3);

8. a) Not stripping trailing space might leave debris the user didn't expect,
but still a choice.

9. a) Always add a last \n. Loss of control by the user.

> On Apr 22, 2019, at 10:15 AM, Brian Goetz <brian.goetz at oracle.com> wrote:
>
>> The main thing Brian is waiting for, though, is not lots of new ideas,
>> but rather a consensus that (a) we can treat leading whitespace outside
>> of a given rectangle as syntax-not-payload (thus stripped), and (b) that
>> we should provide a way for programmers to opt out of the stripping
>> (making all space into syntax-and-payload).  It feels to me like we
>> have arrived there and are driving around the parking lot, checking
>> out all the parking spots, worrying that we will miss the best one.
>
> Glad to hear it :)
>
> So, I posit, we have consensus over the following things:
>
>  - Multi-line strings are a useful feature on their own
>  - Using “fat” delimiters for multi-line strings is practical and intuitive
>  - Multi-line string literals share the same escape language as single-line string literals
>  - Newlines in MLSLs should be normalized to \n
>  - There exists a reasonable alignment algorithm, which users can learn easily enough, and can be captured as a library method on String (some finer points to be hammered out)
>  - To the extent the language performs alignment, it should be consistent with what the library-based version does, so that users can opt out and opt back in again
>  - In the common case, a MLSL will be a combination of some intended and some incidental indentation, and it is reasonable for the default to be that the language attempts to normalize away the incidental indendentation
>  - There needs to be an opt-out, for the cases where alignment is not the default the user wants
>
> (A useful way to frame the discussion we had regarding linguistic alignment is: whether a string literal is “one dimensional” or “two dimensional.”  The 1D interpretation says a string literal is just a sequence of characters between two delimiters; the 2D interpretation says that it has an inherent line structure that could be manipulated directly.)
>
> What I like about this proposal — much more than with the previous round — is that the two flavors of string literal (thin and fat) are clearly projections of the same feature, and their differences pertain solely to their essential difference — multi-line-ness.
>
> I will leave it to Jim to summarize the current state of the alignment algorithm, and any open questions (e.g., closing delimiter influence, treatment of single-line strings, etc) that may still be lingering, but these are not blockers to placing our order for the first two courses.
>
> I am still having a hard time getting comfortable with Guy’s proposal to use more “envelope” here — I think others have expressed similar discomfort.  If I had to put my finger on it, it is that being able to cut and paste in and out is such a big part of what is currently missing, and there is insufficient trust that there would be ubiquitous IDE support in all the various ways that people edit Java code.  But given that this is framed as “let’s carve out some extra envelope space”, we can keep discussing this even as we move forward.
>
> We still need to make some decisions on syntax; the main one that is currently relevant being opt-out. (For any syntax issues, please create another thread.)  Jim hinted at this earlier: use an escape sequence that is stripped out of the string but means “no alignment.”  Something like:
>
>      String s = “"“\-
>          Leave me just the way
>          you found me”””
>
> Obviously there is room to argue over the specific escape sequence, so let’s put this in the “open questions” bucket.
>
> There was another proposal, which was to use a prefix character:
>
>     String s = a”…” // opt into alignment
>     String s = r”…” // raw string
>
> I’d like to put this one to bed quickly, because I see it as having a number of issues.
>
> Having a set of prefix characters is one of those features that starts off weak and scales badly from there :). With only two prefixes, as suggested above, it has a feel of overgeneralization, but with a large number of candidate prefixes, it gets worse, because invariably as such a feature gets more complicated, there are interactions.  One need look only at a Perl regex that uses multiple modifiers:
>
>     /foo*/egimosx
>
> to realize that what started as a simple feature (I think initially just `g`) had grown out of control.
>
> More importantly, of the two prefixes suggested, one doesn’t really make sense.  And that is: while the notion of “raw” string is attractive, one of the things that tripped us up the first time around is the believe that “raw” is a binary thing.  In reality, raw-ness comes in degrees — how hard you have to work to break out of the “string of uninterpreted characters” mode.  (Note: please let’s not start a discussion on raw strings; we’re wrapping up our orders for the first courses now.  I raise this only to put to bed a syntax choice predicated on the assumption that raw-ness is a binary characteristic.).
>
> If we’re pursuing align-by-default, we should consider a different name for the align() method; the name was originally chosen as a compromise when there was no align-by-default, and most of the other names were too long to ask people to type routinely.  If alignment is the default, the explicit name can be more descriptive.
>
>
> So, next steps:
>
>  - Jim to write up current details of alignment algorithm, with current open issues;
>  - Remaining bike sheds on opt-out and naming of align()
>
> Once 1/1a are in the pipe, we can consider whether we want to move ahead to raw strings.
>
>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.java.net/pipermail/amber-spec-experts/attachments/20190422/569b1d14/attachment-0001.html>
```