Yet another terrible compile time argument proposal
Timon Gehr
timon.gehr at gmx.ch
Sun Jan 14 22:15:56 UTC 2024
On 1/14/24 22:27, Steven Schveighoffer wrote:
> On Friday, 12 January 2024 at 22:35:54 UTC, Walter Bright
> [wrote](https://forum.dlang.org/post/unseru$167e$1@digitalmars.com):
>> 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)](https://forum.dlang.org/post/wkwgipddfegevbrimiav@forum.dlang.org) 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:
>
> ```d
> 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:
>
> ```d
> 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](https://forum.dlang.org/post/lplyefclptgxonbzyzzy@forum.dlang.org) 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
See also this: https://forum.dlang.org/post/unsgir$1a5m$1@digitalmars.com
I think there is a way that is somewhat nicer than both of those ideas.
1. Allow `:` syntax for runtime parameters (this already works for
template parameters):
```d
void foo(int x:1, int y){ } // 1
void foo(int x:2, int y){ } // 2
void main(){
foo(1,2); // calls 1
foo(2,3); // calls 2
}
```
2. Make it match during IFTI.
```d
void foo(int x)(int:x, int y){ }
void main(){
foo(1,2); // calls foo!1(2)
foo(2,3); // calls foo!2(3)
}
```
In this example, I have omitted the runtime parameter name, this is
already a D feature.
3. Allow `enum` (and maybe `alias`) storage class on such parameters to
omit them at runtime.
```d
void foo(int x)(enum int:x, int y){ }
void main(){
foo(1,2); // calls foo!1(2)
foo(2,3); // calls foo!2(3)
}
```
Maybe it is best to restrict `:` syntax to `enum` parameters but then at
least the template parameter list is not being modified by the feature.
More information about the Digitalmars-d
mailing list