Discussion Thread: DIP 1036--String Interpolation Tuple Literals--Community Review Round 2
Steven Schveighoffer
schveiguy at gmail.com
Wed Feb 3 16:38:15 UTC 2021
On 2/3/21 10:54 AM, Dukc wrote:
> On Friday, 29 January 2021 at 19:10:55 UTC, Steven Schveighoffer wrote:
>> On 1/29/21 7:58 AM, Dukc wrote:
>>> I was mainly thinking that I'd have easier time differentiating
>>> between an `int` in interpolated string and `int` passed before/after
>>> the interpolated string.
>>
>> We debated whether one should be able to figure out the original
>> interpolation string from the parameters. I don't think it's
>> necessary, and adds unnecessary complexity.
>>
>> Just passing the expression data directly makes things easy to deal
>> with instead of adding an extra type to deal with.
>>
>> If you can come up with a reasonable use case for differentiating, we
>> can discuss.
>
> Okay, finally did this:
>
> ```
> void writeAtPositions(T...)(char[] wArea, T args)
> { import std;
> char[] outp = wArea;
> foreach(arg; args)
> static if(is(typeof(arg) : size_t) && !is(typeof(arg) : char))
> { outp = wArea[arg .. $];
> } else
> { auto argStr= arg.text;
> outp[0 .. argStr.length] = argStr[];
> outp = outp.drop(argStr.length);
> }
> }
>
> void main()
> { import std.stdio;
> char[] text = "x=000,y=000,z=000".dup;
> text.writeAtPositions(2, '2', "55", 16, "6");
> text.writeln;
> }
> ```
>
> Consider passing ints in interpolated strings to `writeAtPositions`.
> Only change needed to work with my suggestion would be adding
> `!__traits(isSame, TemplateOf(typeof(arg), interp))` to the `static if`,
> (I assume interp!int would have `alias value this`). If the interpolated
> string `int`s are passed like any `int`s, one would probably have to
> manually cast the `int`s among interpolated strings to strings, to work
> with this function.
So the idea here is to use string interpolations to represent the string
parts of the parameters.
To reimagine what you are thinking, something like:
int val = 255;
int otherval = 6;
text.writeAtPositions(2, i"${val}", 16, i"${otherval}");
So the parameters are going to be:
text, 2, interp!""(), val, interp!""(), 16, interp!""(), otherval,
interp!""())
First, I'd suggest instrumenting the positions instead of the data,
since that's the exceptional case:
struct Pos { size_t p; }
auto pos(size_t x) { return Pos(x); }
text.writeAtPositions(2.pos, i${val}", 16.pos, i"${otherval}");
And then you have a general mechanism that doesn't even need
interpolation strings:
text.writeAtPositions(2.pos, val, 16.pos, otherval)
And now, you can use interpolation strings as the "things to write"
without ambiguity. You can even use a single interpolation string (with
the positions being interpolation parameters). I would say the
non-interpolation form is better for when you are just passing in
parameters, and the interpolation form is great when you want, well,
interpolations.
I get the thrust of what you are saying. But technically, if you are
having to reengineer the function to deal with interpolation strings,
you should rethink how the API works.
FYI, something I have considered recently, because I don't *love* the
mechanism for overloading is to put a non-template parameter first and
last in the sequence. Which then makes it possible to discover where the
sequences begin and end.
So instead of having to use template constraints for overloading:
void foo(T...)(T args) if (is(T[0] : interp!S, S))
you just use standard overloading:
void foo(T...)(__iStart, T args)
And as a bonus, you can discern interpolation parameters from regular
ones (if desired).
-Steve
More information about the Digitalmars-d
mailing list