| |
 | Posted by Richard (Rikki) Andrew Cattermole in reply to H. S. Teoh | Permalink Reply |
|
Richard (Rikki) Andrew Cattermole 
Posted in reply to H. S. Teoh
|
On 09/09/2025 3:39 AM, H. S. Teoh wrote:
> On Mon, Sep 08, 2025 at 01:09:02PM +1200, Richard (Rikki) Andrew Cattermole via Digitalmars-d-announce wrote:
>> std.format is on my list of modules that I want replaced.
>>
>> Its written with a lot of error conditions, rather than just adapting
>> to the inputs. Hence lots of potential for exceptions being thrown
>> that don't need to be.
>>
>> Multiple multipliers in ``formattedWrite``: format string, output
>> range.
>
> IMO, a lot of template bloat could be removed by internally converting
> output ranges to a delegate of static type that receives a const(char)[]
> and writes to whatever output range was passed in from user code. 90%
> of the std.format code does not actually care for the concrete type of
> the output range; we do not need a copy of the entire formatting code
> for every output range type passed in. Just erase the type at the entry
> function and make most of the formatting code non-templated.
>
>
>> What I'd like to do is to force IES for one or more values, if you
>> want finer grained control you want do one value a time
>> (``formatValue``).
>>
>> ```d
>> writeln(i"$i ${i:X}: $(j + 1)/${(j + 1):X} $1 ${0:X}", k, obj, "atend");
>> ```
>
> I'm still a fan of old-school format strings, I've to admit. Having to
> manually type `formatValue(x), formatValue(y), ...` is just way too much
> boilerplate.
Agreed it is too much boilerplate.
If we have to add a runtime string option then we can, the machinery will all be there.
However it shouldn't be the option people should be reaching for.
How long have we been recommending the template parameter for formatting over the runtime one? A good 10+ years now right.
>> Require the use of a string builder, rather than any old output range.
>
> Too much boilerplate to use a string builder.
Nah.
We use appenders in place of the string builder today.
Its a direct 1:1 swap.
>> This is a required change for pretty printing. It requires the use of
>> arbitrary inserts and removals that ranges can't do.
>
> Format strings should be just strings. It should not accept arbitrary
> ranges (does it do that currently?). Arguments may be ranges.
The reply isn't matching what I said?
>> Every template parameter like these that you have is a multiplier of
>> instances, and that isn't good for compile times. Simplifying them
>> down may seem like a pain, but it helps quite significantly. Given
>> that there are some clear requirements and use cases we can in fact
>> simplify it without hurting anyone enough to care.
>
> See, the thing is that the current implementation of std.format goes
> about things the wrong way. It really should be just a thin wrapper
> template, the sole purpose of which is to unpack the incoming arguments
> and forward them to non-templated formatting functions. Or, at least,
> formatting functions templated only on a *single* argument type (like
> formatValue!int, formatValue!string, formatValue!float, ...), or perhaps
> just overload on various basic types, maybe plus a couple of templates
> for handling structs and classes, not on the entire `Args...` tuple of
> types. The latter causes combinatorial explosion of template instances,
> which is both bloating and needless. Only the top-level
> std.format.format needs to be templated on `Args...`. This should be
> split up so that instead of O(n*m) template instantiations we have only
> O(n) template instantiations (or preferably, O(1) template
> instantiations if all the type-dependent stuff is handled at the top
> level, and all lower-level functions are isolated formatting functions
> that only do one job each).
Looks like its three template parameters: writer, format spec char and value type. Two of which I want gone.
Doesn't appear to have a central dispatcher, its leaving it to overloading which is not a good design IMO.
We'd like it to be closer to mine (although for whatever reason I've still got the builder templated):
https://github.com/Project-Sidero/basic_memory/blob/main/source/sidero/base/text/format/rawwrite.d#L13
> Also, I dream of the day when we can pass compile-time format strings to
> std.format and it will *only* instantiate the formatting functions that
> you actually use. Float-formatting functions are particularly complex
> and bloaty; why should your program pay for that extra baggage if you
> never actually format a float? The various formatting functions should
> be pulled in only when you actually use them. Just because you call
> std.format with "%d" should not also pull in the whole shebang for
> formatting floats, structs, classes, BigInts, and who knows what else.
It already is.
https://github.com/dlang/phobos/blob/master/std/format/internal/write.d#L575
|