The state of string interpolation
Steven Schveighoffer
schveiguy at gmail.com
Fri Dec 7 18:46:05 UTC 2018
On 12/7/18 1:26 PM, H. S. Teoh wrote:
> On Fri, Dec 07, 2018 at 05:11:35PM +0000, Atila Neves via Digitalmars-d wrote:
> [...]
>> Every language change is a cost, and therefore should justify its
>> inclusion. I personally don't think that it is in this case just to
>> make a niche use case slightly easier, and this coming from someone
>> from that niche! From now on it's:
>>
>> const code = mixin(interp!q{
>> // stuff that I used to write with many %s and it was hard to match them
>> up
>> });
>
> One thing I like about format() that string interpolation doesn't
> (easily) give, is the ability to specify additional formatting
> parameters, e.g., %6.2f, or %04X. You'd have to basically "uglify"
> string interpolation in much the same ways in order to get equivalent
> functionality, e.g., (hypothetical syntax) "Price is ${6.2:price}.".
You'd need a valid D expression there with the given proposal (to lower
to a tuple). Something like ${price.formatted!("%6.2s")}.
Or as I had suggested elsewhere, you could use UDAs:
@formatted!("%6.2s") double price;
It's not exactly easy, but it's doable. Plus you could alias it:
alias moneyf = formatted!("%6.2s");
${price.moneyf}
Which makes things actually quite pleasant.
>
> The one thing missing from format(), as you point out above, is the lack
> of named arguments for long format strings. This could be fixed by
> extending format() with named placeholders, so that you can do something
> like:
>
> // Hypothetical syntax
> format(q"CODETEMPLATE
> void %{funcName}s(%{funcParams}(%s, %)) {
> %{boilerPlate}s
> for (i; 0 .. %{numIter}d)
> {
> %{loopBody}s
> }
> }
> CODETEMPLATE", NamedArgs([
> "funcName", "myFunc",
> "funcParams", ["int x", "float y", "string z"],
> "boilerPlate", generateBoilerplate(),
> "loopBody", generateFuncBody(),
> "numIter", 255
> ]));
>
> Basically, instead of sequential arguments (or numerically-indexed
> arguments like $#1), format takes what amounts to a polymorphic
> associative array from which it can look up named arguments. This gets
> rid of the "too many %s I can't figure out which argument is which"
> problem, plus it makes your format string more readable and
> maintainable. It allows the same argument to be referenced multiple
> times, and arguments don't have to appear in the order they appear in
> the format string (important for i18n uses).
The benefit I see from named parameters is using them more than once.
That snippet above is very unreadable IMO.
But just for fun, let's compare to string interpolation strawman:
text(iq"CODETEMPLATE
void ${funcName}(${funcParams.formatted!"%-(%s, %)"}) {
${generateBoilerplate}
for (i; 0 .. ${numIter})
{
${generateFuncBody}
}
}
CODETEMPLATE");
Oh, and it requires zero library support. It just works, as if you
called it with the parameters in the right place.
With:
alias argf = formatted!("%-(%s, %)";
then the function declaration becomes:
void ${funcName}(${funcParams.argf}) {
-Steve
More information about the Digitalmars-d
mailing list