11 hours ago Re: std.format with wstring and dstring | ||||
---|---|---|---|---|
| ||||
Posted in reply to Richard (Rikki) Andrew Cattermole | On Tue, Sep 09, 2025 at 02:26:20PM +1200, Richard (Rikki) Andrew Cattermole via Digitalmars-d-announce wrote: > On 09/09/2025 3:39 AM, H. S. Teoh wrote: [...] > > 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. Oh you mean use a string building internally? That makes sense. I misunderstood, I thought you meant for user code to use a string builder. [...] > > 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. Yeah, the writer should be type-erased to a delegate that receives string data, the format spec should not be templated on char type. Value type should pretty much be the only template parameter. > Doesn't appear to have a central dispatcher, its leaving it to overloading which is not a good design IMO. Yeah it's a mess. :-/ I did look at this code some years ago, hoping to find low-hanging fruits to improve it, but gave up after struggling with the tangled mess that it was in. > 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 Standardizing to a delegate for the builder allows us to swap out different builders without incurring any template bloat. Not sure if that's necessary, but could be a nice escape hatch just in case an unusual case arises. Templates are powerful but sometimes type erasure is called for. > > 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 +1. T -- Talk is cheap. Whining is actually free. -- Lars Wirzenius |
Copyright © 1999-2021 by the D Language Foundation