On Thursday, 7 July 2016 at 16:23:35 UTC, Andrew Godfrey wrote:
So, an example to illustrate the question: In a recent thread, I saw code that used an "alias parameter". I haven't seen this before. Or have I? I'm not really sure, because:
* "alias" is a keyword I've seen before.
* type inference (which I like in general), means that maybe this is the "formal" way to specify whatever it means, and people usually just leave it out.


While I understand the sentiment, I don't think this example is a good one and Andrei answer only makes this more scary.

alias as in alias parameter is the exact same thing as alias in other situations: make this name refers to that other thing.

And here we are touching the problem: why do you expect alias to work in one place and do not expect it to work in other places ? The answer down bellow.

I ask because I see lots of discussions that seem to be proposing a change that will incrementally increase this difficulty. Over time, that would significantly change the language, possibly approaching C++'s level of difficulty, which I'll call "many bridges too far". And C++ seems to have given up fighting this (e.g. I like the idea of the C++ "uniform initialization" and "initializer list" features, but the way their syntax interacts with old-school syntax is frustrating.)


While this very true, it is clear that most D's complexity doesn't come from there. D's complexity come for the most part from things being completely unprincipled and lack of vision.

Let me get back to your alias example. alias does one thing: give a new name to some existing thing. For instance, after doing:

alias foo = bar;

I can use foo as an identifier and it will refer to bar.

Now as to parameters. Parameters are like declarations, but the value is provided in the form of an argument. For instance:

void foo(int a) {} // a is a parameter.
foo(3); // 3 is an argument.

In that specific instance, we conclude that within foo, it is as if we declared int a = 3 (in that specific case).

The concept of alias and the concept of parameter/argument are completely orthogonal, and therefore, there should be no expectation that anything special is going on. So, in

template Foo(alias A) {}
Foo!bar;

Things should be as if, for this specific instance, within Foo, we specified alias A = bar;

Except that it is not the case. D fucks up orthogonality everytime it has the opportunity. As a result, there is a ton of useless knowledge that has to be accumulated. For instance :

alias A = int; // Nope
template Foo(alias A) {}
Foo!int; // OK !

In general, things are so unprincipled that there is no expectation that they are anymore. For instance, you'd expect that

template Foo(T...) {}

would take a variadic number of type as arguments, while

template Foo(alias T...) {}

would take a variadic number of aliases. But no, 1 take a variadic number of aliases and 2/ is invalid. So now we've created a situation where it is now impossible to define variadic, alias and parameter/argument as 3 simple, separate things, but as a whole blob of arbitrary decisions.

This turtles down the the most simple thing:

enum E { A = 1, B = 2 }
E bazinga = A | B;
final switch (bazinga) { case A: ... case B: ... } // Enjoy !

And so on, @safe only mean safe if you do not do this and that, DIP25 is ready to add a new pack of brick to the already tanking Jenga tower. Shared doesn't work and Walter promote use of undefined behavior to work around them.

In fact, when it comes to news feature, more than the added complexity of the feature itself, it it's interaction with existing madness that worries me. Not only there is an explosion of special cases that is completely untractable, but it also cement the existing madness.

Reply via email to