DIP 1027--String Interpolation--Final Review Discussion Thread
Adam D. Ruppe
destructionator at gmail.com
Sun Feb 2 19:36:48 UTC 2020
On Sunday, 2 February 2020 at 18:46:36 UTC, Steven Schveighoffer
wrote:
> The problem I have with the struct mechanism is that it
> enforces the parameters are all non-reffable data.
This is why I at first wanted a pure language solution instead of
the hybrid solution now (language provides syntax sugar, library
provides implementation), but I'm not actually sure this is worth
fighting over.
> int apples;
> int bananas;
> readf(i"I have $apples apples and $bananas bananas");
It is kinda cool that this can work, but really, do you think it
is legitimately useful? readf is so weird in how it works that
you'd very rarely find a case where the interpolated string even
does the right thing.
Moreover, this would also require ref; it wouldn't work with
scanf. So that limits it either more.
But consider if you did want to do something like this, you could
i"$(&apples)"... which actually would work with scanf as well as
with the struct; a pointer can go in there easily enough.
> struct S {}
> foo!(i"I'm passing $S as an alias/type, with some formatting
> data around it");
Again, I think that is cool but not useful enough to justify
compromising other cases. I'll take it if and only if it comes
for free, and the naked tuple does not come for free.
A pure language struct btw can do this - the compiler, instead of
calling a library function, just creates the type internally.
Then it can declare them as aliases as needed. But that opens up
other complications.... and really, what's the value? Why would
you want an alias in the middle of a string? There might be
some... but I can't think of one right now and I suspect there'd
be a better way anyway.
But let's just be careful not to damage real world use cases in
the name of "that might be cool in theory someday". The struct
has definite real world use cases... the alias/ref tuples not so
sure.
> The biggest thing that the DIP has going for it is that there
> are lots of functions which have a format string + args
Yeah, I do like being able to specify a format thingy
(`${%3d}bananas`) in there. That's something I'd definitely see
being legitimately used.
Though I'd probably prefer the format string to be built in a
library, I like that bit enough that I want the magic lowering to
do something with it somehow.
But otherwise it is easy for a library solution to provide format
strings as needed, transparently to the user. And a library
solution can handle the DIP's limitation:
string tool = "hammer";
writefln(i"hammering %s with $tool", "nails");
How? Well, since it is an independent object, it knows what
arguments it had! It could translate itself before going to
outside uses. And especially with a method to produce a format
string, it can even be smart enough to escape % to %% in the
interpolated things.
So that becomes
writefln(_interp!("hammering %s with ", "")(tool), "nails");
and then _interp returns its helper struct. Well, if we do
implicit toString and tool == "%s" well, lol we just poisoned our
format string.
But at the same time, we could provide a method to escape the
interpolated thing - and writefln could overload based on this to
just call that. writeln knows what it needs.
So it'd be like
void writefln(__Interp fmt, ...) {
string f = fmt.toEscapedString!(a => a.replace("%", "%%"));
// forward back to the normal one
writefln(f, ...);
}
Then that toEscapedString method on the struct calls the given
delegate on each user string as it is appended to the final
result. Allowing us to properly encode it in a particular context.
You could us the same thing with html:
string user = "<try_injection>";
string myHtml = i"<b>$user</b>".toEscapedString!htmlEntitesEncode;
// myHtml == "<b><try_injection></b>"
and ditto for any format you can imagine. The struct is flexible
in so many ways that a tuple isn't! And it is easy to use.
Javascript's string interpolation even lets us do this. Do we
want D to be defeated by JAVASCRIPT?!!?!?!?! lol
(this kind of thing btw is another argument against an implicit
toString on alias this. Like I propose that to be friendly to
people who insist `string s = i"$foo";` must work, and it is cool
that we can, though I personally think it should be a decision. I
don't care about GC, but I do care about proper encoding of
output.)
Again, back to your main counter point, do we want to sacrifice
all this *definite* value for possible uses in theory for ref
arguments? I'm not against refness per se (I do find it a lil
weird, but still)... just I don't think it is worth sacrificing
anything for since the to-string potential is far more clear than
the from-string readf potential.
More information about the Digitalmars-d
mailing list