<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>