
Java Feature Spotlight: Text Blocks - chhum
https://www.infoq.com/articles/java-text-blocks/
======
atulatul
This comment is not about text blocks as such but the write up by the author.
(Brian Goetz... If you are here, when do we see the next edition of the book,
please?).

It is not simply 'here's a new language feature'. I find it quite informative
regarding what, why, how and why not etc. His articles explain what went into
the decision making. Something on the lines of discussions in Effective Java
by Joshua Bloch.

His article on records: [https://www.infoq.com/articles/java-14-feature-
spotlight/](https://www.infoq.com/articles/java-14-feature-spotlight/)

------
enitihas
This is a nice feature to have, no doubt, but won't make much difference for
an IntelliJ user. What I am most eagerly waiting for is Loom, that will bring
fibers to the JVM, and make the arguments in favour of server side JVM even
more stronger.

~~~
Scarbutt
'Text Blocks' took many years and you still need pass a flag to use it, I
can't imagine how much time Loom will take. Maybe move to Kotlin coroutines?

~~~
enitihas
I really like Kotlin, but text blocks were never the pain point for me in
Java. The best thing Kotlin brings to the table is explicit nullability, which
makes it so much easier to reason what can be null or not.

Loom and Kotlin coroutines are not the same though. Loom will bring real
fibres to the JVM, which maybe Kotlin coroutines can use. Kotlin coroutines
should also benefit from Loom.

~~~
nickbauman
Am I the only one who really dislikes coroutines?

------
cletus
So this is a long overdue QoL feature but the whole whitespace elision thing
is unwelcome and unnecessary (IMHO). What's wrong with What You See Is What
You Get? This is a perfect example of added complexity to solve a complete
non-problem just based on probably the unsubstantiated aesthetic view of a
handful of key people. Stop. Just... stop.

Even stripping trailing whitespace is... risky. Why is the language trying to
decide what whitespace is significant? Or even trying to divine the mind of
the developer at all?

I didn't realize there was a raw string proposal in Java 12 using backticks
(bleh). By now I'm pretty used to languages that use double-quotes for
interpreted strings (including escape sequences, at a minimum) and single-
quotes for raw strings. This is an incredibly useful feature. Of course, Java
uses single-quotes for character literals so that's out, otherwise I'd like to
see """ for interpreted and ''' for raw.

Anyway, let me point out just one reason why this is terrible: source control.
Consider:

    
    
        String s1 = """
                    <outer>
                      <inner>foo</inner>
                    </outer>
                    """";
    

Now change this to:

    
    
        String s1 = """
                    <outer>
                      <inner>foo</inner>
                    </outer>
                """";
    

It's only one line change but you have in fact changed what the previous lines
do.

And of course (which the article mentions).... tabs!

I really want the option of pasting text into a block like this and knowing
that's what I'll get. I don't want to process it usually (eg escaping
characters).

~~~
vbezhenar
How do you propose handling the most common case, when I don't want leading
indentations?

    
    
        String s1 = """<outer>
            <inner>foo</inner>
        </outer>""";
    

is ugly.

~~~
dfinninger
Python has the textwrap[1] module in the standard library. Calling
“textwrap.dedent()” on the docstring (multiline string) will strip white space
to the least-indented line inside the text.

I’m personally a fan of having an easily-accessible method to call. That way
you get indented text blocks and no “magic” formatting (at least, you
explicitly opt-in to the magic formatting).

[1]
[https://docs.python.org/3/library/textwrap.html](https://docs.python.org/3/library/textwrap.html)

------
yashap
This seems a little too magical for Java - normally indentation doesn’t have
programmatic meaning like this in Java. I prefer the Scala approach:
[https://alvinalexander.com/scala/how-to-create-multiline-
str...](https://alvinalexander.com/scala/how-to-create-multiline-strings-
heredoc-in-scala-cookbook/)

Just seems more obvious/clear.

------
dlandis
> To disentangle the incidental and essential indentation, we can imagine
> drawing the smallest possible rectangle around the XML snippet that contains
> the entire snippet, and treating the contents of this rectangle as a two-
> dimensional block of text. This "magic rectangle" is the contents of the
> text block, and reflects the relative indentation between the lines of the
> block but ignores any indentation that is an artifact of how the program is
> indented.

Well, I'll withhold judgement somewhat until I eventually use this feature for
a little while, but based on the description this is simply too complex, which
is disappointing. Who exactly was asking for the "magical rectangle" approach,
anyway? Or incidental vs essential indentation? They did too much. And given
how long people have been waiting for simple multi-line strings, and how many
other languages already have them, I'm not sure how this got messed up.

~~~
bokchoi
I prefer seeing the multi-line string trimmed to the current indent level. I
wouldn't call it messed up.

------
nickmqb
> Avoid mixing spaces and tabs in the indentation of a text block

This has some implications. For example, I can imagine someone editing a text
block and inadvertently using a different indentation type (tabs/spaces) from
the other existing lines, which would then change their program in a non-
obvious way. I'm myself an author of a programming language with a non-
standard approach to whitespace (called Muon), so this is a topic I've thought
about quite a bit. Interesting that the Java team considers this an acceptable
tradeoff. I'm looking forward to seeing how this plays out in practice as a
data point.

------
strictfp
I much prefer Cs solution to this problem; you can write multiple literals in
sequence and they will be concatenated:

    
    
      char* text = "hello" " dear"
      " sir";
    

This is great, because it doesn't make leading whitespace significant on the
lines which the text block spans.

The Java approach, which seems similar to the Python approach, looks really
silly when you are defining a literal in a nested scope;

    
    
      def hello():
        def world():
          text = """hello
      world"""
          print text

~~~
looperhacks
The difference between Python and Java is that the following (Python):

    
    
        text = """hello
                  world"""
    

will contain the intendation before world, while in Java:

    
    
        String text = """hello
                         world"""
    

will be equivalent to "hello\nworld".

~~~
apk-d
I wish that's how C# handled it! There are verbatim string literals that
support newlines, but in practice, most of the time I see people stick to
regular string concatenation because it ruins code indentation/alignment.
That's how Rider chooses to refactor code when you insert a newline as well.
Multi-line verbatim strings begin to get useful around the point where you
should be probably loading your text from some resource instead of embedding
it in the source.

~~~
ygra
There's plenty of contexts where the extra indentation doesn't matter, though.
And C#'s verbatim strings, at least when it comes to multiple lines, have the
benefit of being extremely predictable in what ends up in the string
(everything, including whitespace). They also have other uses that Java
doesn't even address, like not interpreting escape sequences inside the
string.

I'm not sure you can really compare them. They're two different features with
fairly different uses, it's just that one or two of those uses somewhat
overlap.

~~~
apk-d
They're comparable in the sense that I'm guessing C# is unlikely to get _yet
another_ string declaration syntax, so we're stuck with what we've got.
Regarding predictability I definitely agree, but good syntax highlighting
would help with that.

------
chhum
Interesting to see how Swift-inspired this feature is.

~~~
masklinn
It seems to be using a somewhat similar concept it calls "incidental white
space", in order to limit the embedding of leading whitespace (unlike Python
which just stores the entire triple-quoted string as-is), but is more
permissive:

Text content can be indented less than the trailing delimiter, which I
understand is an error in Swift

    
    
        String html = """
        ..............<html>
        ..............    <body>
        ..............        <p>Hello, world</p>
        ..............    </body>
        ..............</html>
        ..............    """;
    

The trailing delimiter can also be on the same line as the final content,
which suppresses the final (new)line:

    
    
        """
        line 1
        line 2
        line 3"""
    

translates to

    
    
        "line 1\nline 2\nline 3"
    

whereas

    
    
        """
        line 1
        line 2
        line 3
        """
    

translates to

    
    
        "line 1\nline 2\nline 3\n"
    

I believe this _requires_ escaping the newline in Swift instead (nb: according
to the JEP this would also work in Java).

~~~
_old_dude_
Slash at the end of the line serve the same purpose in Java

~~~
masklinn
> Slash at the end of the line serve the same purpose in Java

As I wrote in my comment, yes.

------
nickbauman
Looooong after the other languages have done it, Java comes around to doing
it. Seriously, the best thing about Java is the JVM where you can choose a
better language than Java to program with it and get all the benefits of the
JVM.

~~~
JMTQp8lwXL
If you want to use any language, what makes the JVM important? Just use
whatever that tech stack uses. Node uses v8, for example.

~~~
bpicolo
The ecosystem of supporting libraries for Java is bigger than any other
ecosystem. There's a mature library for every concept in existence. The Node
ecosystem has a lot, but for server-side libs it still doesn't reach the
coverage of Java.

Apache, for example, supports a ton of Java libraries for which there's little
competition, certainly not well distributed across language ecosystems.
PDFBox, Lucene, etc.

When you're in the nitty gritty of automating business processes, that sort of
thing is invaluable. For CRUD-style web services, any language will do the
trick.

(I say this as not a big fan of Java the language)

Python also has a similarly wide ecosystem, and does better specifically in
some regions than any other language, like ML, but a different set of focus
areas. It's probably the other top contender for business-process automation,
but big enterprises prefer OOP/static typing for typical work.

C# probably comes close in many areas, but there's still a split between the
.net core and not-core ecosystems for the long tail of libraries, and no open-
source powerhouse quite like Apache in the mix.

(C/C++ might fall here somewhere too, but I don't know nearly enough about
those language ecosystems to comment)

~~~
MaxBarraclough
> There's a mature library for every concept in existence

If you'll forgive a light trolling: how about ahead-of-time compilation,
allocating small objects on the stack, UTF-8, compile-time asserts, or SIMD
support?

(Was going to include await/async, but then I remembered EA Async.)

I realise this is a little off topic, but the JVM isn't without limitations.
(Or perhaps all my examples are wrong - disproof welcome!)

~~~
doteka
You can get AOT compilation with GraalVM today, allocating small objects on
the stack is being worked on in Project Valhalla, compile time asserts can be
implemented with annotations if you care (see @NotNull), utf-8 is available in
the standard library in the StandardCharsets class.

For Async/await, I believe a much better approach is available with Quasar
today or with Project Loom soon.

SIMD is an issue though if you need that.

~~~
vips7L
AOT was available for over a DECADE with the GNU Compiler for Java before it
was removed.

~~~
MaxBarraclough
It's also long been possible with lesser-known proprietary solutions like
Excelsior JET, so I suppose Java can claim to have a mature solution to that
feature, just not a mature mainstream FOSS solution (not counting Graal).

------
bathtub365
It seems strange to embed content in code in this way. You lose syntax
formatting if it's structured content (HTML, JSON, etc) and also require
recompiling if the content changes. I understand doing it if you're
prototyping/hacking things together but it seems like a lot of effort was put
into building this feature.

~~~
stickfigure
IntelliJ not only handles syntax formatting of code in string literals, but
validates SQL against the db schema and performs identifier completion.

It's more convenient and safer to put SQL (or other text) inline next to the
code that uses it rather than "some other file" that can fall out of sync.

~~~
bathtub365
I guess I don’t have this problem because I don’t work on CRUD apps.

------
nnq
...this is what Java gets instead of smth actually useful like
structs/records/dataclasses with _pass-by-value semantics_?

~~~
enitihas
Java is getting other things, text blocks don't have to be excluded due to
those

1\. Records are already there AFAIK

2\. Structs (Value types) will come as part of Valhalla

3\. Records are the impl of dataclasses

4\. Pass by value is already there for primitive types. Valhalla might bring
that to structs also.

Java is also getting a lot of good stuff like coroutines(Loom), and
Panama(seamless FFI).

~~~
hyperpape
Records are still a preview feature in Java 14 (Apr 2020). Java 15 (Fall 2020)
contains a second preview. They're usable, but you have to pass a flag to the
compiler to enable them, and you run some small risk that the syntax will
change (it's pretty simple, so I'd guess that won't happen).

I'm guessing that they'll land in Spring or Fall 2021, but that's just an
outsider's guess. The really important cutoff is Spring 2022, when Java 18 is
intended to be an LTS version.

~~~
J-Kuhn
You have to pass `--enable-preview` to BOTH compiler and runtime.

If you think about it - the feature may change significantly or be even
removed - it makes sense to only support a preview features in one java
version.

Providing backward compatibility for preview features is simply not intended.

------
dudul
I don't hate Java. It was my 2nd or 3rd language, and the one I first used
professionally. But O-M-G, this feature exists in most mainstream language and
has for the past decade _at least_.

This is nuts to me how behind Java is. Is it only due to the backward
compatibility? Or is there some crazy red tapping every time something is
added?

~~~
jpgvm
It's a combination of things. Java is slow moving by the very nature of the
contributors to the language and runtime favouring slow methodical
advancement.

Additionally Java has a longer history than most of backwards compatible
software that contributes to a higher burden of testing before making changes
to the core language.

Finally there is the community itself which favours high performance and
reliability and prefers where possible to make use of libraries rather than
change the language or runtime itself.

That isn't to say Java isn't evolving or that the JVM itself is stagnant.

The introduction of the Java module system allowed the JRE itself to become a
much lighter dependency. Things like Project Loom seek to bring Erlang-like
fiber/green thread support to the JVM and will probably land in a release
soon.

Also the release cadence has been changed so new releases are now landing much
more frequently which is increasing the pace of development.

~~~
lostmsu
I think at this moment it is fair to say, that Java WAS a slow moving
language. Now it is catching up quickly.

~~~
jpgvm
Yeah I probably should have lead with that.

