Tuples, CTFE, and Sliding Template Arguments

Steven Schveighoffer schveiguy at gmail.com
Sat Jan 13 19:59:08 UTC 2024


On Saturday, 13 January 2024 at 18:43:46 UTC, Nickolay Bukreyev 
wrote:
> On Saturday, 13 January 2024 at 06:46:54 UTC, Walter Bright 
> wrote:
>> So you agree it is not simpler :-)
>
> Let’s compare them side by side.
>

Proposal 1:
> ```d
> // User-library code:
>
> string generateSql(FormatString fmt) {
>     import std.conv: text;
>
>     string sql;
>     int number;
>     for (size_t i = 0; i < fmt.length; ++i) {
>         char c = fmt[i];
>         if (c == '%' && i + 1 < fmt.length && fmt[i + 1] == 
> 's') {
>             sql ~= text('?', ++number);
>             ++i;
>         } else if (c == '%' && i + 1 < fmt.length && fmt[i + 1] 
> == '%')
>             ++i;
>         else
>             sql ~= c;
>     }
>     return sql;
> }
> ```

Note: the above code has a bug in it (I found it when testing), 
it's even easy for the language author to get these things wrong!

Proposal 2:

> ```d
> // User-library code:
>
> string generateSql(Interpolation interp) {
>     import std.conv: text;
>
>     string sql;
>     foreach (i, part; interp.parts)
>         sql ~= i & 0x1 ? text('?', i / 2 + 1) : part;
>     return sql;
> }
> ```
>
> Which one is simpler?

Thank you for showcasing!

I'll add also the code to generate a `writef` format string is 
even easier (if you really wanted to call writef):

```d
string writefFormatString(Interpolation interp)
{
     import std.range : stride;
     import std.algorithm : filter;
     import std.array: join;
     return interp.parts.stride(2).join("%s");
}
```

And of course, sql dialects that use a static placeholder could 
just do:

```d
string mysqlQueryString(Interpolation interp)
{
     import std.range : stride;
     import std.algorithm : filter;
     import std.array: join;
     return interp.parts.stride(2).join("?");
}
```

And in fact, we can provide this as a nice library function for 
users:

```d
string blueprintWithPlaceholder(Interpolation interp, string 
placeholder)
{
     import std.range : stride;
     import std.algorithm : filter;
     import std.array: join;
     return interp.parts.stride(2).join(placeholder);
}
```

>
> (Note that neither of them will actually work due to the fact 
> `FormatString`/`Interpolation` is not the first argument, but 
> that’s not the point I’m arguing here.)

Ugh, I hadn't thought of that. This is kind of a downer for this 
idea. It's... still saveable, but it's not as neat.

-Steve


More information about the Digitalmars-d mailing list