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