<div dir="ltr"><div>Hello!</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sun, Oct 29, 2023 at 2:16 AM Johannes Spangenberg <<a href="mailto:johannes.spangenberg@hotmail.de">johannes.spangenberg@hotmail.de</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><u></u>
<div>
<p>Hello, I recently thought about String Templates and just read
the new JEP 459 for the second preview. I have four comments about
the current JEP, more or less ordered by importance.<br>
</p>
<p><b>1) Unusual generic types for exceptions and return values</b></p></div></blockquote><div><br></div><div>The convenience of generic types is that you don't always need to spell out or even publicly declare the concrete processor type. However, I agree that generic types is not what strictly needed to be mentioned in the specification. We can have</div><div><br></div><div>// This type is mentioned in the specification as the root type of string template</div><div>// clients may implement it directly using more specific return type and exception declaration</div><div>interface Processor {<br></div><div> Object process(StringTemplate template) throw Throwable;</div><div>}</div><div><br></div><div>// This is just a convenient generic subtype, not mentioned in the specification</div><div>// for people who don't want to publicly declare their own types for processors</div><div>@FunctionalInterface<br></div><div>interface ParameterizedProcessor<R, E extends Throwable> extends
Processor {</div><div> R process(StringTemplate template) throws E;</div><div><br></div><div> static <R, E extends Throwable> ParameterizedProcessor<R, E> of(Function<? super StringTemplate, ? extends T> process) {</div><div> return process::apply;</div><div> }</div><div>}</div><div><br></div><div>The problem is more with the naming: how to name these two things to clearly show the difference between them?</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div>
<p>The generic types as specified by JEP 459 look like remnants to
me. Since template expressions are syntactic sugar for method
calls, we should just use the type of the process method, as was
introduced by this JEP. However, the generic types were somehow
left in the JEP. Is there a good reason for that?</p>
<p>For example, <font face="monospace">java.lang.AutoCloseable</font>
does not have a generic type for the exception. The only advantage
I see is that you can implement processors using Lambdas without
introducing a functional interface. How often do you have a
processor that is trivial enough that you see the benefit of using
a lambda? Even the implementation of STR takes multiple lines. If
somebody needs a functional interface, it is trivial to create one
yourself.</p>
<p>In my opinion, the noise introduced by the template parameters
greatly overshadows the advantage of lambdas without having to
declare a functional interface first.</p></div></blockquote><div><br></div><div>On the other hand, you may not have such noise even now, if you declare your own concrete types that inherit the generic processor.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div>
<p>For RAW, STR, and FMT, you may either introduce a sub-interface
without the generic exception or just implement them within their
own class outside <font face="monospace">java.lang</font>.<br>
</p>
<p><b>2) Generic type for embedded expressions</b></p>
<p>While I don't see the value of the existing type parameters, I
think it would be helpful to have a generic type for the embedded
expressions. In contrast to the existing type parameters, such a
type parameter would extend the capabilities. It would be possible
to have type-safe inputs for processors, which is not possible
with the current JEP.</p>
<blockquote>
<pre>public interface StringTemplate<T>
...
public interface Processor<T> {
Object process(StringTemplate<? extends T> st) throws Throwable;
}
...
}
</pre>
</blockquote>
<p><b></b></p></div></blockquote><div><br></div><div>This covers only a limited scenario when all the embedded expressions have the same type. Can you imagine a particular use-case for that scenario?</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><p><b>3) Let STR and FMT keep the indentation<br>
</b></p>
<p>I was wondering if STR and FMT should keep the intention when the
arguments contain line breaks. Most usages are probably not
indented or only use arguments without line breaks. However,
whenever I encountered a situation where I wanted to insert a
multiline string into an indented line, I always wanted to keep
the intention. A potential implementation could basically copy all
the whitespace characters directly after the most recent line
break in the fragments and insert them behind each line break of
the template argument.</p>
<blockquote>
<pre>String multilineString = """
First line.
Second line.
""";
System.out.println("""
Output:
\{multilineString}
...
""");
</pre>
</blockquote>
<p>I have to say I am myself a bit skeptical as this would
noticeably increase the complexity. However, I cannot think of a
scenario where you don't want this to happen. (I could imagine
that I would otherwise implement such a processor in almost all my
projects and end up never using STR.)<br></p></div></blockquote><div>You can use instead </div><div>STR."""</div><div>Output:</div><div>\{multilineString.indent(4)}</div><div>"""</div><div>Which would be more explicit, thus less magical. In general, it's expected that a properly written program would only rarely use STR processor (especially for multiline output), preferring more domain-specific processors depending on how the resulting string should be interpreted.</div><div> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><p>
</p>
<p><b>4) Purpose of StringTemplate.interpolate()?</b><br>
</p>
<p>And finally, although not very important, I am wondering about
the usefulness of <font face="monospace">StringTemplate.interpolate</font>.
In the rare case when you actually need this functionality, you
can also call <font face="monospace">STR.process(template)</font>.
There is also <font face="monospace">template.process(STR)</font>
for some reason.</p>
For <font face="monospace">toString()</font>-like use cases, we
already have <font face="monospace">StringTemplate.toString(StringTemplate)</font>.
I don't think that <font face="monospace">StringTemplate.interpolate()</font>
would be a good fit in such cases. And again, you can otherwise
still call <font face="monospace">STR.process(...)</font>.<br>
<p><br>
</p>
<p>That was all. I am happy for any reply.<br>
</p>
<p>PS: I find it interesting that the JEP does not mention tagged
templates of JavaScript, although the concepts look quite similar.</p>
<p>Best Regards,<br>
Johannes<br>
</p>
</div>
</blockquote></div></div>