Thread overview
Template value inference: closing the UFCS gap for template value parameters (or, "foo".format(bla) as a template instantiation)
Aug 05, 2019
FeepingCreature
Aug 05, 2019
Olivier FAURE
Aug 05, 2019
FeepingCreature
Aug 10, 2019
Nick Treleaven
Aug 11, 2019
Nick Treleaven
August 05, 2019
Right now, we can write format("Hello %s", 5), or we can write "Hello %s".format(5). This is an appealing syntax that also appears in other languages like Python.

To take advantage of compile-time parameter checking, we can also pass the format string as a template parameter: format!"Hello %s"(5). If I'd called with (5, 6), it would have been a compile error. However, there is no equivalent UFCS syntax for templated-formatstring format!

Forms like "Hello %s".!format(5) seem obvious, but look ugly. Luckily, there's an easier way.

With something like format("Hello %s", 5); the types of the parameters to format are translated into template type arguments; in other words, this is equivalent to format!int("Hello %s", 5). Let's call this template type inference.

Since D templates have value parameters, this suggests an analogous process of template value inference. How would this look?

void format(string fmt, T...)(fmt, T args);

In other words, we specialize format for the *value* of the template parameter fmt, and then let IFTI/template inference do the work of figuring out the appropriate template instantiation, exactly as before.

With this change, format!"..." would no longer be necessary at all; all format calls of the form format("format string", args) would be templated on the string's value, as they already are on the argument types.

Thoughts?
August 05, 2019
On Monday, 5 August 2019 at 06:49:32 UTC, FeepingCreature wrote:
> Since D templates have value parameters, this suggests an analogous process of template value inference. How would this look?
>
> void format(string fmt, T...)(fmt, T args);

I'd suggest

    void format(enum Fmt: string, T...)(Fmt fmt, T args);

That said, does the use case of needing UFCS with a template for a formatting string come up *that* often?
August 05, 2019
On Monday, 5 August 2019 at 08:42:29 UTC, Olivier FAURE wrote:
> On Monday, 5 August 2019 at 06:49:32 UTC, FeepingCreature wrote:
>> Since D templates have value parameters, this suggests an analogous process of template value inference. How would this look?
>>
>> void format(string fmt, T...)(fmt, T args);
>
> I'd suggest
>
>     void format(enum Fmt: string, T...)(Fmt fmt, T args);
>

Seems extraneous. Enums are not types, fmt is not a variable. You'd basically be messing with the type system (introducing static single-value types, similar to the range propagation magic) for the sake of syntax. Besides, we already have a syntax for template value parameters.

> That said, does the use case of needing UFCS with a template for a formatting string come up *that* often?

I mean, we're using format!"" exclusively, for typechecked safety. We actually have a regex that translates "foo".format() into format!"foo"() form. It would be nice to not have to do that, especially since ufcs form really is more readable. More than that, though, it is such a logical extension of how templates already work that I think it should work for that reason alone.

August 10, 2019
On Monday, 5 August 2019 at 06:49:32 UTC, FeepingCreature wrote:
> void format(string fmt, T...)(fmt, T args);
>
> In other words, we specialize format for the *value* of the template parameter fmt, and then let IFTI/template inference do the work of figuring out the appropriate template instantiation, exactly as before.
>
> With this change, format!"..." would no longer be necessary at all; all format calls of the form format("format string", args) would be templated on the string's value, as they already are on the argument types.
>
> Thoughts?

Sounds great. I think the main advantages are optimization and compile-time checking rather than UFCS.

IFTI should prefer template value parameter inference over an overload that takes the parameter at runtime. (The overload is still necessary for non-literal arguments).

Then we could call a function with compile time optimization without even having to be aware of a template overload that takes a literal value argument at compile-time instead of runtime.
August 11, 2019
On Saturday, 10 August 2019 at 17:55:14 UTC, Nick Treleaven wrote:
> (The overload is still necessary for non-literal arguments).

Where I said literal, I meant compile-time known value.