I get that and brace choice is a bit arbitrary but I think indexing would be a
fairly frequent use case. You end up with "\[array[i]]". The Swift parentheses
"\(array[i])" style is better than brackets because we are use to
parenthesizing expressions. But in the end, braces are rarely used in
expressions and the braces visually pop the embedded expression "\{array[i]}".
I think this is because we are conditioned to think of braces as being
outermost bracketing.
Cheers,
— Jim
📱
On Apr 11, 2023, at 6:13 PM, Tagir Valeev <[email protected]> wrote:
Hello!
As we're here, I wonder whether \[...] was considered. I see a big advantage
over \{...}, because one doesn't need to hold shift key to type [ in widely
used US-qwerty layout (and some other widely used layouts as well). Such
character sequence is much easier to type.
With best regards,
Tagir Valeev
On Tue, Apr 11, 2023, 22:36 Jim Laskey
<[email protected]<mailto:[email protected]>> wrote:
Begin forwarded message:
From: Jim Laskey <[email protected]<mailto:[email protected]>>
Subject: Re: Syntax question for JEP 430: String Templates
Date: April 11, 2023 at 1:11:58 PM ADT
To: Octavia Togami <[email protected]<mailto:[email protected]>>
Cc: [email protected]<mailto:[email protected]>
Octavia,
I’m assuming you want ${…} used because that’s what many other languages use
(if that is not the reason, apologies). I would argue that it is an advantage
for Java not to use what other languages use. More on that toward the end of
this reply.
JEP 430 indicates why \{…} was chosen and I don’t think the reasoning is
weakened by the processor expression prefix requirement.
- Backslash was chosen because the combination of \{ would not create
compatibility issues with older Java source.
- Braces were chosen because it is less likely that braces would be used in an
embedded expression (versus parentheses and brackets). Note that Swift uses
\(…).
Using ${…} to indicate embedded expressions would create two distinct
categories of quoted elements, that is, ${…} would be lexically different for
strings versus templates. Sounds simple, but tools wouldn't know which way to
tokenize the quoted element until the tool’s grammar detected the "processor
dot template" context (and note that processor can be a complex expression).
Since most tools separate scanning (lexicon, tokens) from parsing (grammar)
this forces the tooling to provide some sort of feedback between the lexicon
and grammar — gets messy.
Using \(…) makes it easy for javac to tokenize both strings and templates
without feedback from the parser. Note that you would have to add a new escape
sequence for $ if you want to use $ in the template.)
Other languages can support ${…} at the lexicon level because their strings
were designed to support ${…} from the beginning or have simple ways to
indicate that the quoted element needs to be treated differently — different
quotes, tag prefix, … .
Back to what I stated at the beginning, I think that \{…} is an advantage for
string templates in much the same way that triple quotes works for text blocks,
\{…} doesn’t conflict with other languages. Java serves a polyglot universe,
where it is not uncommon to embed other language source in a Java app. For
example;
Object result = JAVASCRIPT."""
let header = "Templates Literals";
let tags = ["template literals", "javascript", "es6"];
let html = `<h2>${header}</h2><ul>`;
for (const x of tags) {
html += `<li>${x}</li>`;
}
html += `</ul>`;
""";
or
Object result = BASH."""
Recipient=”[email protected]<mailto:[email protected]>”
Subject=”Greeting”
Message=”Welcome to our site”
`mail -s ${Subject} ${Recipient} <<< ${Message}`
""";
Though you would not have the advantage of embedded expressions, it is also
possible to use ${…} for your own style of template. We assume existing
template libraries will provide similar StringTemplate “bridging".
static final StringTemplate.Processor<StringTemplate, RuntimeException>
MY_STYLE = st -> {
String text = st.interpolate();
Pattern p = Pattern.compile("\\$\\{(.*?)\\}");
Matcher m = p.matcher(text);
List<String> fragments = new ArrayList<>();
List<String> values = new ArrayList<>();
int last = 0;
while (m.find()) {
fragments.add(text.substring(last, m.start()));
values.add(m.group(1));
last = m.end();
}
fragments.add(text.substring(last));
return StringTemplate.of(fragments, values);
};
public static void main(String[] args) {
StringTemplate mailer = MY_STYLE."""
Dear ${name},
This is to inform you that your ${package} will be
delivered on ${date}.
Respectfully,
Big Shop
""";
Map<Object, Object> data = Map.of(
"name", "Joan",
"package", "bicycle",
"date", "May 31"
);
System.out.println(StringTemplate.interpolate(
mailer.fragments(),
mailer.values().stream().map(data::get).toList()
));
}
-----------------------------------------------------
Dear Joan,
This is to inform you that your bicycle will be
delivered on May 31.
Respectfully,
Big Shop
-----------------------------------------------------
Hope this frames a better understanding.
Cheers,
— Jim