Tuples, CTFE, and Sliding Template Arguments

Walter Bright newshound2 at digitalmars.com
Mon Jan 15 01:27:00 UTC 2024


I'll summarize up front, and so one can skip the detailed reply below. It's 
obvious there's no meeting of the minds here. I'll just explain where I'm coming 
from.

Features doing simple things should be simple. That's the case with 1027. Doing 
complicated things should be expected to be more complicated to use. With 1036, 
it starts out at the other end. It's complicated, with complexity that one has 
to write additional code to make it simple again (the "filter out the 
unnecessary templates" thing we talked about).

It's fine that transmorgrifying the string to adapt it to SQL has complexities 
to it. That's expected. If that's all string interpolation would be used for, 
that's ok.

But people want to use string interpolation for mixins, etc., all that have 
nothing to do with SQL. The transmorgrification should not be necessary for 
those cases, it should just work. But it doesn't, if the filter isn't applied 
there's a significant runtime and code space cost.

Simple things should be simple, complicated things should expect complexity. But 
1036 has simple things being complicated. Doing SQL is about the same level of 
complexity for 1027 as 1036. For doing simple things, 1036 remains complicated, 
and 1027 gets simple.

That's the extent of my unease with it.

Does 1027 do *everything* 1036 does? No. There's the Format can be implicitly 
converted to a string thing. So there's a tradeoff. Do we trade off a minor 
thing for a fair amount of complexity that yes, the user will see? Every feature 
in D is a compromise of one sort or another. I fall on one side of that, you the 
other.

Another illustration of this idea. For algorithmic code, I invented opApply(). 
But after experience with it, I slowly grew to dislike it because I could never 
remember how it worked, and would have to reread the documentation on it. The 
implementation of it is also ugly, as it has to rewrite the code that surrounds 
it. Heaven help anyone who has to read the code gen output of that. I much 
prefer the later approach using lambdas. They're simple, easy to remember and 
use. There isn't much implementation for them; they grew naturally out of other 
features in the language.

The one thing that lambdas don't do that opApply does is recursion. Some klunky 
code has to be written to make a lambda do recursion. But that's ok, as there 
are relatively few needs for recursion, so the simple cases with lambdas are 
simple, and the complicated cases are more work. This is as it should be.

Nothing comes for free, everything is a compromise.

----------------------------

On 1/13/2024 9:12 AM, Steven Schveighoffer wrote:
> This doesn't help, as an enum implicitly converts to its base type.

It's a point for 1036.


> In none of the proposals I have written or supported, has it been meant for 
> `writef`. I don't understand the desire to hook `writef` and `format`.

A format string is needed to support formats like "%03d". I understand that is 
not needed for SQL, but support for formats is not so straightforward with 1036.


> Me too. But shouldn't we prefer compiler errors? Shouldn't we use the type 
> system for what it is intended?

We should prefer compiler errors, I agree. But everything has a cost to it.


> I've literally left bugs like this in code for years without noticing until the 
> actual thing (an exception) was printed, and then it was hours to figure out 
> what was happening.

When I've had an exception printed, I'll grep the code base for the message to 
see where it came from. The message should also say what was wrong. If it's a 
generic exception, I'll use the debugger to find where it came from. I doubt a 
format string error would be hard to track down, as it's only one level below 
the cause of the error.


> This would be a step up, but still doesn't fix the format specifier problem.

I'm not seeing a format specifier problem. %s, ?1, what's the difference? What 
if the string literals generated by 1036 have a stray ?1 in them? If there's a 
check for that, I missed it.


> Without a trailer, this isn't solvable technically.

It can by counting arguments and the %s.


> I just meant that it isn't a requirement to disallow them somehow.

I did mention a way it can work.


> The SQL example *DOES NOT* generate a format string, I've told you this multiple 
> times. It generates a string with placeholders. There is no formatting. In fact, 
> the C function doesn't even accept the parameters, those happen later after you 
> generate the prepared statement.

CTFE work is required to generate both "hello ?1 ?2" and "hello %s %s". I 
understand your point that the latter requires an unacceptable level of CTFE 
processing, though I don't agree with the "unacceptable" part. I don't see how 
1036 is going to deal with stray ? in the string literals without CTFE.


> Things other than SQL *do not require building a string*.

Building a format string enables formats other than %s. For example, %03d. Adam 
wrote a library function for that, 
https://github.com/adamdruppe/interpolation-examples/blob/master/lib/format.d 
which does a lot of CTFE. Noted in it is "the format string is built at compile 
time".
	>> I suspect you routinely use CTFE for far, far more complex tasks. This is a
>> rounding error.
> Wait, so generating an extra template is a bridge too far, but parsing a DSL at 
> compile time is a rounding error?

It's ((number of args) - 1)*2+3 templates. Looking at the object file, they are 
templates with pretty long names, along with their struct instantiations, which 
is not free in compiler time or memory consumption.


> Not to mention that concatenation is easy. I can do it in one line (if I don't 
> really care about performance). The same cannot be said for parsing.

As you mentioned before, the code only has to be written once!



More information about the Digitalmars-d mailing list