Marco Leise:

The amount of possible use-cases you listed for this extension
is staggering.

With scope management in code like this:


import std.stdio, std.algorithm;
int foo(in int[] a) {
    return sum([0, 1] ~ a[1 .. $ - 2] ~ 0 ~
               [a[$ - 1] + 1, a[$ - 1] + 2]);
}
void main() {
    int[5] b = [10, 20, 30, 40, 50];
    b.foo.writeln;
}


The compiler in theory could lower the code to something like this, removing all heap allocations for the array literals and the concatenations, allowing 'foo' to be annotated with @nogc (I don't know if Rust is able to do this, I presume it can):


import std.stdio, std.algorithm, core.stdc.stdlib;
T foo(T)(in T[] a) @nogc {
    immutable size_t L = 2 + a.length - 3 + 1 + 2;
    auto ptr = alloca(T.sizeof * L);
    if (ptr == null)
        exit(1); // Or throw a stack overflow error.
    T[] b = (cast(T*)ptr)[0 .. L];
    b[0] = 0;
    b[1] = 1;
    b[2 .. $ - 3] = a[1 .. $ - 2];
    b[$ - 3] = 0;
    b[$ - 2] = a[$ - 1] + 1;
    b[$ - 1] = a[$ - 1] + 2;
    return sum(b);

}
void main() {
    int[5] c = [10, 20, 30, 40, 50];
    c.foo.writeln;
}


But in some cases you don't want those arrays to be allocated on the stack because you know they are very large. So the [...]s array literal syntax becomes useful again:

import std.stdio, std.algorithm;
int foo(const scope int[] a) {
    return sum([0, 1]s ~ a[1 .. $ - 2] ~ 0 ~
               [a[$ - 1] + 1, a[$ - 1] + 2]s);
}


But this is still not enough, because even if those parts are all safely stack-allocated, the result of the concatenation is still not stack-allocated.


This could be enough:

import std.stdio, std.algorithm;
int foo(const scope int[] a) @nogc {
    auto[$] a2 = [0, 1]s ~ a[1 .. $ - 2] ~ 0 ~
                 [a[$ - 1] + 1, a[$ - 1] + 2]s;
    return sum(a2[]);
}

Bye,
bearophile

Reply via email to