Interpolated strings

H. S. Teoh via Digitalmars-d digitalmars-d at puremagic.com
Wed Apr 19 13:02:24 PDT 2017


On Wed, Apr 19, 2017 at 06:38:13PM +0000, Patrick Schluter via Digitalmars-d wrote:
[...]
> As a string interpolation sceptic I have to admit that I found one
> application of that concept that is probably much better than the
> current C derived format strings: Internationalisation.
> 
>     dates["en"] = "The date is %2$02d-%1$02d-%3$04d";
>     dates["fr"] = "La date est %1$02d-%2$02d-%3$04d";
> 
>     writeln(format(dates[lan], day, month, year));
> 
> with interpolation we have
> 
>     dates["en"] = $"The date is {month:%02d}-{day:02d}-{year:04d}";
>     dates["fr"] = $"La date est {day:%02d}/{month:%02d}/{year:04d}";
> 
> which is a little bit easier to read than positional format specifiers,

Somebody proposed some years ago to add named parameter support to
format strings (if not to D itself). So ostensibly, instead of writing
the nastiness like the above "La date est %1$02d...", you'd be able to
write something like:

     dates["en"] = "The date is %{month}02d-%{day}02d-%{year}04d";
     dates["fr"] = "La date est %{day}02d-%{month}02d-%{year}04d";

     writefln(dates[lan], [ "day": day, "month": month, "year": year]);


> which have the added backdraw (at least in C, I don't know for D) that
> they are an none or ALL thing. When you need them, you have to put
> them an all format specifiers.

I think std.format.format actually allows you to mix positional and
non-positional specifiers in the same format string. But the semantics
have some tricky bits, though, so I wouldn't recommend doing it.


> This said, the interpolation has in that case a big drawback, i.e.
> that they "export" the variable names outside of the scope they are
> defined in. That's a thing that is often required for I10N, that the
> strings are defined in a separate file or module and selectively
> imported (at runtime).

With named parameter support in format strings, we wouldn't have this
problem, since you could name the parameters however you want regardless
of actual variable names. You could even perform arbitrary computations
on the variables before passing it to format, e.g.:

	writefln("The date is %{year}04d-%{month}02d-%{day}02d", [
		"year": yearsSinceEpoch + 1970,
		"month": zeroBasedMonth + 1,
		"day": zeroBasedDay + 1
	]);

This way, implementation details like zero-based counting, years since
the Unix Epoch, etc., are kept within the code where it belongs, not in
the i18n strings.

I'd argue that interpolated strings have a disadvantage here, because
you wouldn't want to expose the computation `yearsSinceEpoch + 1970` to
the l10n translators, who may inadvertently modify the expression to
something wrong. Plus, allowing arbitrary (Turing-complete!) expressions
inside l10n strings is just a security exploit waiting to happen.


T

-- 
Bare foot: (n.) A device for locating thumb tacks on the floor.


More information about the Digitalmars-d mailing list