On Saturday, 1 May 2021 at 00:13:08 UTC, Paul Backus wrote:
> On Friday, 30 April 2021 at 16:20:13 UTC, sighoya wrote:
> Relates to the following:
https://devblogs.microsoft.com/dotnet/welcome-to-c-9-0/#target-typed-new-expressions
What do you think about?
I'm not a fan of expressions that require context to determine their type.
D already has a few of these for built-in types; for example:
int[] a1 = [1, 2, 3];
double[] a2 = [1, 2, 3];
The issue is that, while [1, 2, 3]
can be either an int[]
or a double[]
in "normal" code, it's always an int[]
in generic code. So if you write something as simple as
int[3] a1 = [1, 2, 3].staticArray;
double[3] a2 = [1, 2, 3].staticArray;
...you get a type error:
Error: cannot implicitly convert expression staticArray([1, 2, 3]) of type int[3] to double[]
Have you ever seen this beauty:
int[] xs = [ 2: 3, 0: 1 ];
assert(xs == [1, 0, 3]);
Notice how the size is not clear, like, at all!
In my mind-model, literals are not “expressions that require context to determine their type” but rather have their own type that's not spelled-out in any way, but has clearly defined operations, especially implicit casts. typeof
won't infer that special type, quite to the contrary, typeof
will give you a reasonably general type for the literal. If lit
is a literal, it can happen that, as an expression, using lit
alone works, but (cast(typeof(lit)) lit)
will fail:
int[] xs = cast(typeof([ 2: 3, 0: 1 ]))[ 2: 3, 0: 1 ]; // error
For that reason, one cannot refactor literals into enums like an idiot because enums must have a spelled-out type and enum varName = expr;
is identical to enum typeof(expr) varName = expr;
.
enum lit = [ 2: 3, 0: 1 ];
int[] xs = lit; // error: cannot implicitly convert ... `int[int]` to `int[]`
I don't even think polysemous values (learned the term recently) are a bad idea, they're practically useful in many cases. I just think the D spec should be more open about it.
Before I forget it: [ 2: 3, 1 ]
works as an expression for int[]
, but not for int[int]
, and typeof([ 2: 3, 1 ])
does not compile and neither does D infer a template type for it. (It's D's version of “Initializer lists have no type!” by Scott Meyers¹.) Worse, even if a slice type is hinted, it won't compile:
void f(T)(T[]) { pragma(msg, T); }
f([ 2: 3, 1 ]); // expect: T == int, but error