On Sunday, 25 August 2024 at 05:07:43 UTC, Manu wrote:
>This is a really old drum to beat on... but maybe we need to start pounding
it again.
It's not strictly this simple though; I think there's a lot of work up-front. We don't really even know what a tuple is, or even what "kinds" of things the language can express...
Like, there's more than types and values. There's symbol aliases, which may or may not carry an instance reference with them, declaration aliases, which may carry names and properties like storage class, there's sometimes expression aliases, there's potentially attributes, and heaps of other stuff that exists outside the language; like storage class, which doesn't seem to have any presence in the language at all; it's queried with a __traits and comically tells you those facts as string literals! I think this space might be the heart and soul of D's foundational issues, and as such, it's excruciatingly hard to make corrections.
Like, from my example above, what even IS s.tupleof
? It's some kind of
list of what kind of thing? Direct symbol references to members of a live
instance?
If s.tupleof can populate a list with that kind of thing, why doesn't this
work:
struct S
{
int x, y;
}
struct T
{
S s;
int i;
alias a = i; // works
alias b = s.x; // Doesn't work? Why?
}
All good points I think. AliasSeq and aliases in general have always been a sore spot in D meta.
>It seems like s.tupleof presents that there are semantics in the language to express this sort of thing, but it's not clear what to call that.
Likewise in my example above:
alias a = s.tupleof; // this can hold the list of references, which seem to
carry around their instance reference with them
alias b = s.tupleof[0]; // this emits a surprising error message:
error : alias b
cannot alias an expression AliasSeq!(s.x, s.y)[0]
So, that 'list' I mention; does this error message imply that this list given by tupleof
is an AliasSeq? What exactly IS an AliasSeq? What is the actual set of things that it can hold?
If tupleof is an AliasSeq, then what's going on here:
alias c = AliasSeq!(s.tupleof);
alias d = c[0]; // the error is now gone??
At first, I was thinking WTF is this? How can this work?
But the answer is, it doesn't.
if you try to use d
you will get an error, because there is no instance -- you ended up aliasing the symbol without the instance.
I almost feel like we need a distinction between alias-with-instance and alias-of-symbol.
There are more WTFs, like in certain cases aliases will carry along names along with the types, and in some cases they don't.
I remember classically this pattern (before static foreach):
foreach(i, _unused; x.tupleof)
{
// use x.tupleof[i] here instead of _unused, because the former gives names
}
> I think a good indication that this whole space is profoundly troubled when classic patterns like this emerge:
template T(alias X) { use X } // oh no you don't, alias is very
opinionated! you'll need this instead:
template T(X...) if (X.length == 1) { use X[0] }
This is no longer needed, so at least there is a bit of progress.
>No matter how you look at it though, this shouldn't be a valid forum post in 2024...
Agreed.
-Steve