Wanted: Format character for source code literal

Q. Schroll qs.il.paperinik at gmail.com
Tue May 4 18:02:50 UTC 2021


On Tuesday, 4 May 2021 at 07:54:19 UTC, Berni44 wrote:
> On Monday, 3 May 2021 at 23:08:55 UTC, Q. Schroll wrote:
>> Please don't do this. Format characters can be customized. Any 
>> character you'd introduce for it either wouldn't work for some 
>> types or break those types' formatting.
>
> I think, this doesn't hurt: The call of a `toString` has 
> precedence for compound types like structs and classes (and in 
> most of these cases it won't be possible to add a generic 
> literal at all, see my post above). So, if you use some of the 
> predefined qualifiers, the customized version will always be 
> used, even if it has a completely different meaning. 
> (Admittedly it might cause some confusion, if the customized 
> versions are not well documented.)

What you wrote in parentheses is _exactly_ the problem I have 
with this. Generic code cannot use it because user defined types 
regularly hook the format. If you use `%D` format, but the type 
does not support it (say std.typecons.Tuple), it will throw a 
FormatException.
So you're stuck between a rock and a hard place: Give `%D` 
preference over custom format specifiers rendering those that use 
`%D` invalid or let `%D` do its custom stuff if *potentially* 
supported rendering `%D` useless in generic code where most of 
its use-cases would lie.

>> Why not introduce a new function like `dlangLiteral` that 
>> takes the value and returns a string? It can be used in 
>> `format` quite easily (like `format("pre %s post", 
>> dlangLiteral(<something>));`) and is explicit and not a 
>> special case at all.
>
> In my opinion, the main idea behind this formatting routines 
> is, to have a simple and short way for formatting output. We 
> could use your idea for every other format character too, like: 
> `format("%s = %s", character('𝜋'), 
> scientificFloatingPoint(3.14))`. We don't do that, because it's 
> more convenient to write `format("%c = %e", '𝜋', 3.14)`.

Yes, you could. But you could use format specifiers like `%-3.8f` 
*without losses* to get to the same result. And that's *the* 
difference between introducing a format specifier character that 
should have generic meaning and introducing, well, anything else. 
There was no problem introducing separators like `%,3d` and 
neither would there be a problem introducing `%y` for `int` or 
`double` (whatever it does), or, for a concrete example, `%S` for 
`bool` to return `TRUE` instead of `true`.

The problem is introducing *generic* format specifier 
*characters*.

> An other problem will be, when used with arrays, ranges and the 
> like, e.g. you can do something like `format("val = [%(%D,\n
>  %)];", my_array);` to get an output with each value on a 
> separate line. Without this literal you would at least need to 
> map `my_array` using `dlangLiteral` and in generic code this 
> might even cause more trouble.

If you want that, you need to allow something that's currently 
illegal. As a comparison, `%.*f` could be introduced if `*` 
precision weren't already a thing (compare with `%,3d`) because 
in any reasonable implementation, `*` instead of precision would 
be an error. What we could do is special casing `%$` to mean what 
you want. Currently, no matter what type you're formatting, `%$` 
is an error in `FormatSpec`. You can give it semantics, no 
problem, including one that ignores custom formatting. Even 
better, `%$` looks like it's a special case and not some 
odd-but-legal custom specifier.

Changing the meaning of `%D` begs for trouble.


More information about the Digitalmars-d mailing list