<div dir="ltr"><div>Hello, Maurizio!</div><div><br></div><div>Thank you for the detailed explanation!</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Mar 11, 2024 at 1:16 PM Maurizio Cimadamore <<a href="mailto:maurizio.cimadamore@oracle.com">maurizio.cimadamore@oracle.com</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>
    <div>
      <p style="margin:0px 0px 1.2em">Hi all,<br>
        we tried mainly three approaches to allow smoother interop
        between strings and string templates: (a) make String a subclass
        of StringTemplate. Or (b) make constant strings bs <em>convertible</em>
        to string templates. Or, (c) use target-typing. All these
        approaches have some issues, discussed below.<br>
      </p>
      <p style="margin:0px 0px 1.2em">The first approach is
        slightly simpler, because it can be achieved entirely outside of
        the Java language. Unfortunately, adding “String implements
        StringTemplate” adds overload ambiguities in cases such as this:</p>
      <pre style="font-family:Consolas,Inconsolata,Courier,monospace;font-size:1em;line-height:1.2em;margin:1.2em 0px"><code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;background-color:rgb(248,248,248);white-space:pre-wrap;overflow:auto;border-radius:3px;border:1px solid rgb(204,204,204);padding:0.5em 0.7em;display:block">format(StringTemplate) // 1
format(String, Object...) // 2
</code></pre>
      <p style="margin:0px 0px 1.2em">This is actually a
        very important case, as we predice that StringTemplate will
        serve as a great replacement for methods out there accepting a
        string/Object… pack.</p>
      <p style="margin:0px 0px 1.2em">Unfortunatly, if
        String <: StringTemplate, this means that calling format with
        a string literal will resolve to (1), not (2) as before. The
        problem here is that (2) is not even applicable during the two
        overload resolution phases (which is only allowed to use
        subtyping and conversions, respectively), as it is a varargs
        method. Because of this, (1) will now take the precedence, as
        that’s not varargs. While for String::format this is probably
        harmless, changing results of overload selection is something
        that should be done with care (esp. if different overloads have
        different return types), as it could lead to source
        compatibility issues.</p></div></div></blockquote><div>I would still like to advocate for String <: StringTemplate solution. I think that the overloading is not a big problem. Simply making String implements StringTemplate will not break any of existing code because there are no APIs yet that accept the StringTemplate instance. The problem may appear only when an API author actually adds such an overload and does this in an incompatible way with an existing String overload. This would be an extremely bad design choice, and the blame goes to the API author. You've correctly mentioned that for String::format this is harmless because the API is well-designed. We may suggest in StringTemplate documentation that the API designers should provide the same behavior for foo(String) and foo(StringTemplate) when they add an overload.</div><div><br></div><div>I must say that we already had an experience of introducing new interfaces in the hierarchy of widely-used library classes. Closable got AutoClosable parent, StringBuilder became comparable, and so on. So far, the compatibility issues introduced were tolerable. Well, probably I'm missing something but we have preview rounds just for this purpose: to find out the disadvantages of the approach.</div><div><br></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><div>
      <p style="margin:0px 0px 1.2em">On top of these
        issues, making all strings be string templates has the
        disadvantage of also considering “messy” strings obtained via
        concatenation of non-constant values string templates too, which
        seems bad.</p></div></div></blockquote><div>I think that most of the APIs will still provide String overload. E.g., for preparing an SQL statement, it's a perfectly reasonable scenario to have a constant string as the input. So prepareStatement(String) will stay along with prepareStatement(StringTemplate). And people will still be able to use concatenation. I don't think that the absence of String <: StringTemplate relation will protect anybody from using the concatenation. On the other hand, if String actually implements StringTemplate, it will be a very simple static analysis rule to warn if the concatenation occurs in this context. If the expected type for concatenation is StringTemplate, then something is definitely wrong. Without 'String implements StringTemplate', one will not be able to write a concatenation directly in StringTemplate context. Instead, String-accepting overload will be used, and the expected type will be String, so static analyzer will have to guess whether it's dangerous to use the concatenation here. In short, I think that it's actually an advantage: we have an additional hint here that concatenation is undesired. Even compilation warning could be possible to implement.</div><div><br></div><div>So, I don't see these points as real disadvantages. I definitely like this approach much more than adding any kind of implicit conversion or another literal syntax, which would complicate the specification much more.<br></div><div><br></div><div>With best regards,</div><div>Tagir Valeev.</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><div>
    </div>
  </div>

</blockquote></div></div>