String Interpolation Compare - DIP1027 and YAIDIP

Walter Bright newshound2 at digitalmars.com
Sat Oct 21 01:50:33 UTC 2023


https://github.com/dlang/DIPs/blob/master/DIPs/rejected/DIP1027.md

https://github.com/John-Colvin/YAIDIP

Both designs fulfill their basic function of string interpolation, and both are 
user extensible to enable most anything. They look rather alike. Beyond that, 
they are quite different. DIP1027 is based around the printf()/writef()/format() 
model, while YAIDIP is based on the write() model. DIP1027 generates a format 
string followed by arguments to it, YAIDIP generates a template instance 
followed by a sequence of string arguments.

The rest is about differences that matter. Of course I'm biased about this - I 
went looking for fault and found it. It's better to find fault in advance rather 
than belatedly, because whatever we pick we're going to be stuck with. I 
strongly favor designs that are self-evident and require minimal to no 
documentation. I prefer designs that are simple building blocks, where the user 
can combine such blocks to form more complex designs. Designs that have minimal 
special cases and fit with the rest of the language are better.

As with Ddoc and unittest, designs that don't address every need, but cover the 
vast bulk of needs with a simple self-evident design, are better designs.

I apologize for any typos and mistakes due to misunderstanding YAIDIP.

# YAIDIP

## Pros

1. Is less susceptible (but not immune) to accidentally matching the wrong 
function or template.

## Cons

1. It's inefficient because of more than double the number of arguments that 
have to be passed.

2. It's inefficient because it requires the arguments to be converted to string 
temporaries, and then the strings are appended to the result. This is both slow, 
and requires string memory allocations. In contrast, a formatter (like printf 
and writef) does not require string intermediates, the generated characters can 
be sent directly to the sink.

3. To get anything other than the default conversion, such as adding leading 
spaces, writing a formatting conversion function is necessary, and then called. 
This means the i-string is going to get quite long. Consider the difference between:

```
     i"axy:  ${%03d}a ${%e}x ${%20.10f}y"  // DIP1027
```
```
     i"axy:  $leadingZero$digits(3)$a $scientific$x $fixed(20,10)$y" // YAIDIP
```

If there are more than a small number of embedded arguments, the length of the 
i-string becomes untenable and unreadable. The compact formatting language, 
which has been pretty standard for nearly 50 years, is a lot easier to deal with.

4. If the manipulators are not in scope, there's no way to qualify them with the 
'.' syntax. Temporary aliases are necessary:

```
     alias leadingZero = std.istring.leadingZero;
     alias digits = std.istring.digits;
     alias scientific = std.istring.scientific;
     alias fixed = std.istring.fixed;
     i"axy:  $leadingZero$digits(3)$a $scientific$x $fixed(20,10)$y"
```

5. The tuple output, which the user is sooner or later going to be confronted 
with, looks like (copied from YAIDIP):

```
     writeln(.object.imported!"core.interpolation".InterpolationHeader!("", "x", 
" can be written as ", scientific, "", x, " or ", fixed(20, 10), "", x, ".")(),
   x, " can be written as ", scientific, "", x, " or ", fixed(20, 10), "", x, ".");
```

This will show up in error messages, and the user is confronted with how the 
sausage is made. I had to read YAIDIP several times to try to figure out what 
that text actually meant. Contrast that with:

```
     writefln("%s can be written as %e or %20.10f", x, y);
```

where it is simple and self-evident what is happening.

6. It requires another template added to object.d, which is already so bloated 
with templates it consumes a large compile time penalty. It requires the user to 
understand this template.

7. It requires the creation of another module, call it `std.istring`, to contain 
all the manipulators a user will expect to see (such as `scientific`).

8. There will be difficulties using this with betterC because of the required 
string allocations mentioned earlier.

9. i-strings are special case behaviors for pragma, mixin, assert, static 
assert, function calls, constructor calls, and template instantiations. They are 
not general purpose. They cannot be used for things like generating tuples for 
other uses.

----------------------------------------------

# DIP1027

# Pros

1. does not require memory allocation

2. does not require object.d support

3. does not require a library of manipulators

4. works out of the box with all the existing formatted string functions, and 
leverages the decades of optimizations that the C formatted string functions 
employ, along with existing knowledge of those functions and how they work

5. can do everything YAIDIP does

6. is faster

7. uses less memory

8. does not emit template bloat into the object files

9. does not emit structs into the object files

10. the i-strings are much more compact

11. generates a tuple that is self-evident

12. generates a tuple that can be used anywhere tuples work

# Cons

1. Is more susceptible to inadvertent matching with the wrong function, because 
the tuples generated are tuples of strings, integers, and other ordinary types.

-----------------------------

Nothing is perfect, but DIP1027 is a much better fit for D's style of simple 
elegance.


More information about the Digitalmars-d mailing list