[string-templates] Simplify custom processor creation

Tagir Valeev amaembo at gmail.com
Mon Nov 27 17:44:01 UTC 2023


Hello, Jim!

It's still a lot of ceremony, so if I need this functionality, I would not
use it directly and rather create a function like withToString shown above.
I'm not sure that there could be another moving part in common
applications, other than object->string conversion. Please correct me if
I'm wrong.

With best regards,
Tagir Valeev

On Mon, Nov 27, 2023, 18:40 Jim Laskey <james.laskey at oracle.com> wrote:

> I’d recommend using the two argument StringTemplate.interpolate for this
> sort of use case. Process values as a stream and then feed to
> StringTemplate.interpolate(fragments, values).
>
> static final StringTemplate.Processor<String, RuntimeException> HEXER = st -> {
>     List<String> values = st.values()
>             .stream()
>             .map(v -> v instanceof Integer i ? "0x" + Integer.toHexString(i)
>                                              : String.valueOf(v))
>             .toList();
>     return  StringTemplate.interpolate(st.fragments(), values);
>  };
>
> public static void main(String... args) {
>     int x = 10, y = 20;
>     System.out.println(HEXER."\{x} + \{y} = \{x + y}");
> }
>
>
> 0xa + 0x14 = 0x1e
>
>
>
> On Nov 27, 2023, at 1:00 PM, Tagir Valeev <amaembo at gmail.com> wrote:
>
> Hello!
>
> As we expect that people will create custom template processors, we can
> simplify their lives.
>
> First, it could be common to add a finisher transformation to an existing
> processor. I think that for many purposes it would be enough to use STR
> processor as a starter, and then create a custom domain object from the
> resulting string. This could be simplified if we add a method 'andThen' to
> the Processor interface:
>
> default <RR> Processor<RR, E> andThen(Function<R, RR> finisher) {
>     Objects.requireNonNull(finisher);
>     return st -> finisher.apply(process(st));
> }
>
> Second, I think that many processors may want to keep string parts intact
> but handle embedded expressions in a special way, effectively replacing the
> default 'String.valueOf' behavior of the standard STR processor. We can
> provide a way doing this, encapsulating all the ceremony. Something like
> this:
>
> static StringTemplate.Processor<String, RuntimeException> withToString(Function<Object, String> toStringFunction) {
>     Objects.requireNonNull(toStringFunction);
>     return st -> {
>         StringBuilder sb = new StringBuilder();
>         Iterator<String> fragIter = st.fragments().iterator();
>
>         for (Object value : st.values()) {
>             sb.append(fragIter.next());
>             sb.append(toStringFunction.apply(value));
>         }
>
>         sb.append(fragIter.next());
>         return sb.toString();
>     };
> }
>
> withToString(String::valueOf) should be equivalent to the STR template (in
> functionality, not in performance)
>
> Now, one can easily build interesting things like:
>
> StringTemplate.Processor<Pattern, RuntimeException> REGEXP =
>    withToString(obj -> Pattern.quote(obj.toString())).andThen(Pattern::compile);
>
>
> What do you think?
>
> With best regards,
> Tagir Valeev
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-spec-observers/attachments/20231127/43a63d89/attachment-0001.htm>


More information about the amber-spec-observers mailing list