←back to thread

620 points tambourine_man | 2 comments | | HN request time: 0.413s | source
Show context
pansa2 ◴[] No.43750383[source]
> t-strings evaluate to a new type, `string.templatelib.Template`

> To support processing, `Template`s give developers access to the string and its interpolated values before* they are combined into a final string.*

Are there any use-cases where processing a Template involves something other than (i) process each value, then (ii) recombine the results and the string parts, in their original order, to produce a new string? In other words, is the `process_template` function ever going to be substantially different from this (based on `pig_latin` from the article)?

    def process_template(template: Template) -> str:
        result = []
        for item in template:
            if isinstance(item, str):
                result.append(item)
            else:
                result.append(process_value(item.value))
        return "".join(result)
I haven't seen any examples where the function would be different. But if there aren't any, it's strange that the design requires every Template processing function to include this boilerplate, instead of making, say, a `Template.process` method that accepts a `process_value` function.
replies(3): >>43750478 #>>43753470 #>>43757222 #
1. rfoo ◴[] No.43750478[source]
There are a lot of examples about SQL in comments. In the SQL case you want something like:

  def process_template(template: Template) -> tuple[str, tuple]:
    sql_parts = []
    args = []
    for item in template:
      if isinstance(item, str):
        sql_parts.append(item)
      else:
        sql_parts.append("?")
        args.append(process_value(item.value))
    return "".join(sql_parts), tuple(args)
(of course it would be more nuanced, but I hope you get the point)
replies(1): >>43750614 #
2. pansa2 ◴[] No.43750614[source]
Yes that makes sense, thanks.

Also, my comment was about the amount of boilerplate required, but that can be vastly reduced by writing `process_template` in a more functional style instead of the highly-imperative (Golang-like?) style used in the article. The first `process_template` example is just:

    def process_template(template: Template) -> str:
        return ''.join(interleave_longest(template.strings, map(process_value, template.values)))
And the second is something like:

    def process_template(template: Template) -> tuple[str, tuple]:
        return (
            ''.join(interleave_longest(template.strings, ['?'] * len(template.values))),
            map(process_value, template.values)
        )