Just another example of missing string interpolation

Adam D Ruppe destructionator at gmail.com
Thu Oct 19 02:47:47 UTC 2023


On Thursday, 19 October 2023 at 00:57:35 UTC, Walter Bright wrote:
> The lowering to arguments to InterpolatedExpression seem to all 
> be string versions of the argument identifiers, rather than 
> what the types are.

The types are attached to the parameters themselves, so it is 
purely redundant to list them again. The interpolated header's 
job is to preserve the original string, allowing for compile time 
manipulation of it. The arguments are processed the same as any 
other `T...` tuple in D.

> "the header gives the callee complete access to the strings 
> corresponding to the expressions passed in."
>
> I don't know what that is useful for. Note that if write() is a 
> template, it already has access to all the arguments and their 
> types.

The strings are not the types. The compiler has this information, 
the user wrote it, even if you don't see the value, why discard 
it?

But here's one example: this year's DConf had a talk on gnu 
gettext. In current D code, they use a template argument string 
to make a user-defined literal which is collected into the 
translation files. This is pretty cool. But it loses some 
information, comments are added by hand:

tr!("One license.", "%d licenses.", Context(“driver's"))(n);

With the interpolation header, it could quite plausibly be:

tr(i"One license.", i"$(driversLicenseCount) licenses.");

(i renamed the variable there because it is now meaningful so you 
can).

The full string written in the source - i"$(driversLicenseCount) 
licenses." - is available for inspection. The tr function can 
even extract that variable name and automatically add it as a 
comment to the translator, giving them the additional context 
without needing to write it again in the code.

It also potentially opens up library implementations of something 
like assert with checkaction=context, showing the original code 
that led to the result.

Please note that it is just a string in another scope, it is not 
useful for `mixin` or anything like that. You still inspect the 
*value* using the argument. But the *string* can be used as a 
*string* for these other tasks.

> I'd like to see an example of code of how this customization 
> might work, because I don't see it.


Element makeHtmlFromTemplate(T...)(T t) if(T.length && is(T[0] == 
core.interpolation.InterpolationHeader!Parts, Parts...)) {
     string html;
     foreach(idx, str; Parts) {
       if(idx % 2 == 0)
         html ~= str; // i know this is html string literal thanks 
to noramlization
       else
        // note i also know what code this came from in case i 
need it for error messages, debug info, etc, it is in `str`
         html ~= htmlEntitiesEncode(to!string(t[idx / 2]));
     }

     return Element.make(Html(html));
}


auto element = makeHtmlFromTemplate(i`
    <html>
       <p class="foo" title="$(title)">
            $(content)
       </p>
    </html>
`);


Note the VERY important fact that the makeHtmlFromTemplate *knows 
for a fact* what is html and what is data coming from the 
outside, so it can be sure about what to encode and what not to.

Also worth noting it has the option of validating the HTML at 
compile time, using CTFE, because it can reconstruct the string 
from the InterpolationHeader too - this is a runtime error in 
most languages, but in D it doesn't have to be.

Javascript can do this kind of thing, with runtime error 
throwing. The JSX extensions to the language exist to add compile 
time validation. D ought to be able to do the same thing 
*without* a custom add-on compiler. We have CTFE.


> P.S. there are several errors in the document, such as '$' 
> appearing in the lowered code. What "normalization" means is 
> unclear.

typos are irrelevant but whatever i'll fix them. "Normalization" 
means what it says under the "normalization" header, which 
ensures you can distinctively tell the difference between format 
string and arguments.


More information about the Digitalmars-d mailing list