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