Feedback Wanted on Homegrown @nogc WriteLn Alternative
H. S. Teoh via Digitalmars-d
digitalmars-d at puremagic.com
Fri Oct 3 09:59:48 PDT 2014
On Fri, Oct 03, 2014 at 11:15:28AM +0000, monarch_dodra via Digitalmars-d wrote:
> On Thursday, 2 October 2014 at 23:32:32 UTC, H. S. Teoh via Digitalmars-d
> wrote:
> >Alright, today I drafted up the following proof of concept:
> >
> >[...]
> >
> >writefln!"Number: %d Tag: %s"(123, "mytag");
>
> I had (amongst with others) thought about the possibility of
> "ct-write".
>
> I think an even more powerful concept, would rather having a "ct-fmt"
> object dirctly. Indeed writefln!"string" requires the actual format at
> compile time, and for the write to be done.
>
> It can't just validate that *any* arbitrary (but pre-defined) string
> can be used with a certain set of write arguments.
>
> I'm thinking:
>
> //----
> //Define several format strings.
> auto english = ctFmt!"Today is %1$s %2$s";
> auto french = ctFmt!"Nous sommes le %2$s %1$s";
>
> //Verify homogeneity.
> static assert(is(typeof(english) == typeof(french)));
>
> //Chose your format.
> auto myFmt = doEnglish ? english : french;
>
> //Benefit.
> writfln(myFmt, Month.oct, 3);
> //----
>
> I think this is particularly relevant in that it is these kinds of cases
> that are particularly tricky and easy to get wrong.
So ctFmt would have to be a static type that contains static information
about the number and types of formatting items it expects? Because
otherwise, we won't be able to do checks like verifying at compile-time
that the passed arguments match the given format.
But if we're going to go in this direction, I'd also introduce
named parameters instead of positional parameters, which would make
translators' jobs easier. For example:
ctFmt!"Today is %`day`s %`month`s"
is far easier to translate correctly than:
ctFmt!"Today is %1$s %2$s"
where the translator may have no idea what %1$s and %2$s are supposed to
refer to. For all they know, %1%s could be "our" and %2$s could be
"anniversary".
> For "basic" usage, you'd just use:
> writefln(ctFmt!"Number: %d Tag: %s", 123, "mytag");
>
> The hard part is finding the sweet spot in runtime/compile time data,
> to make those format strings runtime-type compatible. But it should be
> fairly doable.
Personally, I prefer the shorter syntax for the most usual cases where
the format string doesn't change:
writefln!"Number: %d Tag: %s"(123, "mytag");
But ctFmt could also fit under this scheme when more flexibility is
desired: we could pass it as a first parameter and leave the default CT
parameter as "" (meaning, read args[0] for format string). So if args[0]
is an instance of ctFmt, then we can do (more limited) compile-time
checking, and if it's a runtime string, then fallback to the current
behaviour.
For a compile-string that's statically fixed (i.e.,
writefln!"..."(...)), we can do a lot more than what ctFmt does. For
example, we can parse the format at compile-time to extract individual
formatting specifiers and intervening string fragments, and thereby
transform the entire writefln call into a series of puts() and
formattedWrite() calls.
With ctFmt, you can't extract the intervening string fragments
beforehand, and you'll need runtime binding of formatting specifiers to
arguments, because the exact format string chosen may vary at runtime,
though they *can* be statically checked to be compatible at compile-time
(so "X %1$s Y %2$s Z" is compatible with "P %2$s Q %1$s R", but "%d %d
%d" is not compatible with "%f %(%s%)" because they expect a different
number of arguments and argument types). So I see ctFmt as an object
that encapsulates the expected argument types, but leaves the actual
format string details to runtime, whereas passing in a string in the CT
argument of writefln will figure out the format string details at
compile-time, leaving only the actual formatting to be done at runtime.
T
--
Truth, Sir, is a cow which will give [skeptics] no more milk, and so
they are gone to milk the bull. -- Sam. Johnson
More information about the Digitalmars-d
mailing list