| Field | Value |
|---|---|
| DIP: | 1039 |
| Review Count: | 1 |
| Author: | Lucien Perregaux |
| Implementation: | None |
| Status: | Withdrawn |
Allow $ in the brackets of array declarations in place of integer literals in order to infer array length.
It is sometimes necessary to modify the contents of an existing static array initializer. For example,
int[2] array = [2, 4];may at some point be changed to
int[3] array = [2, 4, 6];The programmer must remember to update the integer literal in the static array declaration from 2 to 3, else face a compiler error.
The goal of this proposal is to eliminate the need to change the length specified in a static array declaration, with minimal impact on compile time, when modifying the length of the array's initializer.
Allowing the compiler to infer static array length will potentially save time and prevent compiler errors,
as the programmer will no longer need to change the integer literal in the array declaration.
This is especially beneficial when using betterC, where dynamic arrays are not available.
Conceptually, the new operator [$] documents that the programmer does not care about the array's length,
but only that the array is a static array and not a slice.
No control-flow analysis is needed for this feature.
In C and C++, we can declare a static array with inferred length like this:
int arr[] = {1, 2, 3};In D, the identical syntax
int[] arr = [1, 2, 3];is a slice, and not a static array.
See this C array initialization documentation.
- The
$operator, which is well implemented. - PR 3615
- Reverted due to partial deduction PR 4373
- PR 590
- Issue 14070
- Issue 8008
This feature is compatible with betterC and is only available for variable declarations with initializers.
The $ in the array declaration's brackets will be replaced, at compile time, with the initializer's length.
Currently, a static array must be declared like this:
uint[2] arr = [ 2, 4 ];When doing this, we have a DRY violation because we are spelling out the array's length even though the compiler knows the length of the array literal used to initialize it.
With the proposed feature, the above array could be declared like this:
uint[$] arr = [ 2, 4 ]; // $ = 2There is no need to change the length of the static array every time we modify the length of its initializer. Eliminating that need is the only goal of this proposal.
More examples:
char[$] a1 = "cerise"; // OK, `$` is replaced with `6` at compile time
const int[] d = [1, 2, 3];
int[$] a2 = d; // OK, `$` = 3
auto a3 = cast(int[$]) [1, 2, 3]; // OK, `a3` is `int[3]` (same behavior as `cast(int[3])`)
int[$][] a4 = [[1, 2], [3, 4]]; // OK, same as `int[2][]`
foreach (int[$] a; a4) {} // OK, we can deduce `$` because the length of `a4[0]` is equal to 2.
void foo(int[$] a5 = [1,2]); // OK, `a5` has a default value, so we can deduce it's length
int[5] bar();
int[$] a6 = bar(); // OK, `bar` returns a static array.Those examples won't work:
int[$] b1; // Error: we don't know the length of `b1` at compile-time.
int[$][] = [[1, 2],[1, 2, 3]]; // Error: cannot implicitly convert expression `[[1, 2], [1, 2, 3]]` of
// type `int[][]` to `int[2][]`
/*
* `$` is equal to `3`, because it's the length of `b2[0]`.
* As `b2[1]`'s length is 4, a RangeViolation error is thrown.
*/
int[][] b2 = [[1, 2, 3], [1, 2, 3]];
foreach (int[$] b; b2) {} // Error: we don't know the length of `b` at compile-time.
void foo(int[$] b3); // Error: we don't know the length of `b3` at compile-time.
int[$] bar(int[2] arr) // Error: not allowed in functions declarations
{
return arr ~ [3, 4];
}
int baz(int[$] b5)(string s); // Error: not allowed in templates declarations
int[] d = [1, 2];
int[$] b6 = d; // Error, we don't know the length of `d` at compile-time.TypeSuffix:
*
[ ]
+ [ $ ]
[ AssignExpression ]
[ AssignExpression .. AssignExpression ]
[ Type ]
delegate Parameters MemberFunctionAttributes
delegate Parameters
function Parameters FunctionAttributes
function Parameters
2. Arrays read right to left as well:
int[3] x; // x is an array of 3 ints
int[3][5] x; // x is an array of 5 arrays of 3 ints
int[3]*[5] x; // x is an array of 5 pointers to arrays of 3 ints
+int[$] x = [ 0, 1 ]; // x is a static array of 2 ints
+int[$][] x = [[0, 2], [1, 3]]; // x is a dynamic array of static arrays with a length of 2None
Copyright (c) 2020, 2021 by the D Language Foundation
Licensed under Creative Commons Zero 1.0
- The DIP should provide a rationale as to why the feature is not allowed in function declarations.
- The DIP does not provide enough examples; it should clearly demonstrate behavior for every situation in which a type can be used. The DIP author agrees.
- The DIP should explain what the problem was with the first attempt and how this proposal address that problem. The DIP author disagrees.
- The DIP should specify if arrays of character types include a terminating
\0and, if so, if it is part of the length. - The DIP fails to provide a rationale as to why
std.array.staticArrayis insufficient. - Better examples are needed. The DIP author agreed.
- The DIP should use ease of reading/writing code as an argument and provide examples to that effect. The DIP author agreed.
- The benefit gained is very minor, so the DIP should address this in relation to the difficulty of the implementation and maintenance. The DIP author agreed.
After the first round of Community Review, the DIP author felt that the general opinion of the DIP was negative, and that he needed to revise the DIP with a strong argument in favor of the proposed feature over std.array.staticArray. He was unable to formulate such an argument, so he asked that the DIP be withdrawn.