On Friday, 12 January 2024 at 22:35:54 UTC, Walter Bright wrote:
>Given the interest in CTFE of istrings, I have been thinking about making a general use case out of it instead of one specific to istrings.
Been also thinking about this and I have the following conclusions:
- Walter's proposal seems super hacky and probably shouldn't be done. I don't like the idea of magically migrating an argument from one place to match a parameter in another, especially based on arbitrary rules that are constructed to fit the current use case (and in fact was shown not to actually help in the long run.
- I really really like the idea of passing a simple struct at either runtime or compile time to a function over instrumented parameters (like the
InterpolationLiteral!"str"
or Rikki's attribute passing (which basically becomes extra hidden template parameters, that the function might not even use). - The syntax for any such mechanism should be obvious and straightforward.
Instead of pushing runtime value arguments into compile time value parameters, why not just identify that they are compile time in the argument list? I like the idea from Mathis Beer (FeepingCreature) that was linked by Nick earlier, but that also has some (I think) ambiguous syntax, and requires some coordination between separate parts.
I'm going to propose something that furthers the baggage of enum
, but that is the tool we currently have... Happy to think about better syntax. But why not just:
void foo(T)(T x, enum string s)
{
pragma(msg, s); // s is compile-time
}
void main(string[] args)
{
foo(1, "hi"); // ok
foo(1, "hello"); // ok, but a different instantiation
foo(1, args[1]); // error, second argument must be compile time
}
Basically, an enum attributed parameter in the runtime parameter list requires a compile-time value, and implicitly adds it to the template arguments for the template instantiation. This is very similar to FeepingCreature's proposal, but without the extra ambiguity. There is no mechanism to explicitly pass the parameter in the compile-time arugment list.
Details can be worked out. But first wanted to see if it makes preliminary sense to everyone? I'm looking specifically at language experts, what am I missing?
In reference to the SI proposals (and keep in mind, this is still orthogonal to the format string vs. interpolation segments, which I'm still firmly on the side of passing the parsed data to the user), it could look something like this:
struct Interpolation
{
immutable string[] parts;
}
auto execi(Args...)(Database db, enum Interpolation interp, Args args)
{
enum sqlStr = generateSQLString(interp);
return exec(db, sqlStr, args);
}
The beauty of this is, the string interpolation proposal becomes a direct translation from the string literal to a sequence of simple values (similar to DIP1027).
I know one point from Jonathan/Nickolay has already been brought up against this idea:
On Sunday, 14 January 2024 at 07:54:23 UTC, Nickolay Bukreyev wrote:
>On Sunday, 14 January 2024 at 02:49:24 UTC, Jonathan M Davis wrote:
>And I'd really rather not have runtime arguments silently become compile-time arguments base on how a function signature is written (which could change when the code is refactored).
Agreed.
[story about removing unnecessary template instantiations by searching for !]
I see this point. I don't know how to reconcile my desire to have an expression that has compile-time data passed through it, while having it be an expression that works wherever expressions are expected, without having to separate the two into the compile time and runtime pieces. It's just so ugly, and things really should be where they belong cognitively.
I'm open to alternatives. Or preliminary limitations. But that is the gist of it -- I want compile-time information passed via a string interpolation tuple, like it is for DIP1036e.
-Steve