New operators opStaticIndex and friends

angel andrey.gelman at gmail.com
Tue May 14 17:27:25 UTC 2019


On Tuesday, 14 May 2019 at 15:49:51 UTC, Q. Schroll wrote:
> I whish, D has these operators:
>
> opStaticIndex
> opStaticIndexAssign
> opStaticIndexOpAssign
> opStaticSlice
>
> When used, they look the same way as opIndex and friends, but 
> the stuff between [ and ] would be bound to template parameters 
> (instead of runtime parameters) and be known at compile time. 
> Basically, this allows to implement static indexing the same 
> way it is possible for an AliasSeq.
>
> Furthermore, it is possible to have static and dynamic indexing 
> next to each other. This is supported by static-size arrays 
> (e.g. int[3]) only: https://run.dlang.io/is/99g01e
>
> Implementing e.g. tuple-like structures, it would be valuable 
> to have both. Dynamic indexing would only be present (design by 
> introspection) if the contents support it.
>
>   struct S
>   {
>     enum int opStaticIndex(int index) = index + 1;
>     int opIndex(int index) { return index + 1; }
>
>     enum size_t[2] opStaticSlice(size_t i, size_t j) = [ i, j ];
>
>     void opStaticIndexAssign(int index)(int value);
>     void opStaticIndexAssign(int i, int j)(int value);
>     void opStaticIndexAssign(size_t[2] slice)(int value);
>     void opStaticIndexOpAssign(string op, int index)(int value);
>   }
>
>   S s;
>   int i = s[0]; // rewrites to s.opStaticIndex!(0), as 0 can be 
> used for the template parameter
>   int j = s[i]; // rewrites to s.opIndex(i), as i cannot be 
> read at compile-time
>
> The "Static" variants would be preferred when determining which 
> one to lower to.
>
> s[0] = 1; // rewrites to s.opStaticIndexAssign!(0)(1)
> s[0, 2] = 1; // rewrites to s.opStaticIndexAssign!(0, 2)(1)
> s[0 .. 2] = 1; // rewrites to 
> s.opStaticIndexAssign!(s.opStaticSlice!(0, 2))(1)
> s[0] += 1; // rewrites to s.opStaticIndexOpAssign!("+", 0)(1)
> s[0, 2] += 1; // rewrites to s.opStaticIndexOpAssign!("+", 0, 
> 2)(1)
>
> Currently, there is no way to implement custom compile-time 
> indexing. Only using alias-this to an AliasSeq can do 
> something, but is very limited. The alias-this is shadowed by 
> any presence of opIndex.
>
> An alternative would be a `static` or `enum` storage class for 
> function runtime parameters that only bind to values known at 
> compile-time.
> These have been proposed years ago and would not only solve 
> this but also format!"fmt" vs. format(fmt) and friends.
>
> I have no knowledge about the DMD implementation, but I'd 
> intuitively expect that new operator rewrites would be much 
> less work to implement.
>
> Do you want it? Do you see problems? Should I clarify 
> something? Is it worth writing a DIP?


You say:
int i = s[0]; // rewrites to s.opStaticIndex!(0), as 0 can be
int j = s[i]; // rewrites to s.opIndex(i), as i cannot be read at 
compile-time

But actually, in this example, s[i] CAN be figured out at 
compile-time.
What is even more problematic is that the ability of the compiler 
to figure out the value of 'i' and s[i] at compile-time might 
depend on the optimization level, thus you cannot be sure whether 
s.opStaticIndex!(1) or s.opIndex(i) will be called.

IMHO, s[0] is already calculated in compile-time when appropriate 
optimization level is invoked ... at least it should've been.


More information about the Digitalmars-d mailing list