The state of string interpolation
Jonathan Marler
johnnymarler at gmail.com
Fri Dec 7 05:38:13 UTC 2018
On Friday, 7 December 2018 at 00:43:43 UTC, Mike Franklin wrote:
> I know I'm just thinking out loud and not contributing much,
> but I can't help but feel that there's something common in all
> these ideas that just hasn't been identified yet. And no,
> Jacob, not AST macros (Actually, that would probably do it, but
> I think we've already been there) :D
>
> Mike
The truth is, we already have a feature that allows us to do
this, its "mixin". I empathize with the feeling that there must
be something else out there that allows us to do interpolation as
a library, but I think you'll find there just isn't.
As D exists today, with a library solution, we need 2 extra
"composed" function calls to `mixin` and the "interpolating"
function. Plus we need an extra import to include the
interpolating function.
import std.typecons : interp;
writeln(mixin(interp("a is $(a)")));
Even if we could make mixin a little more friendly, you still
have:
import std.typecons : interp;
writeln(interp("a is $(a)").mixin);
These 2 extra calls are the difference between string
interpolation spreading like an infectious disease and being
completely useless. String interpolation in this form is
laughable when you compare it to existing solutions:
writeln("a is ", a);
writeln("a is %s", a);
For comparison, here's the simple language solution for it:
writeln(i"a is $(a)");
Looking for a feature that can enable "interpolation as a
library" as well as other constructs is the right question.
You're looking for a feature that's almost as powerful as mixin
but also doesn't require the caller to be so verbose. This is
where the rubber meets the road. Sadly, no such feature can or
should exist. If you allow functions to have this power you are
going to make the language impossibly hard to understand moving
forward. Any function now has the ability to reach into their
caller's scope meaning you now have to understand the source of
every function to know how it affects any and all of your local
data. There's no more isolation, local variables are now almost
as bad as global variables **shudder**.
Interpolation is an interesting case because it can reach into
the caller's scope, but all the code to access locally scoped
state is inside the string being interpolated at the call site.
Here's the way I see it:
Allowing a library to write functions that reach into their
caller's scope breaks the assumed isolation between functions.
This means that no data is safe, any function could mess with
your data at any time. We don't want that, so this means if we
want interpolation to be a library, then the caller MUST invoke
`mixin`. But for string interpolation to be adopted, it needs to
be less verbose than current solutions which is impossible if it
needs to use mixin. Thus we arrive at an impass. We want to
implement interpolation as a library but it can't be done well
enough unless we break function encapsulation. Assuming all of
this logic is correct, the only conclusion is that interpolation
requires language support.
All that being said, if someone does find a feature that allows
interpolation as a library without mixin and without breaking
function isolation then great. But no feature has been found yet
and my confidence that no such feature can exist is growing over
time. At some point we'll have to admit the unicorn doesn't exist
so let's stick a horn on our horse and paint it...it's not as
pretty as the unicorn, but at least its real :)
More information about the Digitalmars-d
mailing list