Walter Bright:

> The previous behavior for function parameters can be retained by making 
> it a ref parameter:
>     void foo(ref T[3] a)

If I have generic code, like a templated function, that accepts both a dynamic 
and a static array, the function call will change its performance signature 
according to the type (if I don't add a "ref" the pass of a dynamic array will 
be O(1) while passing a fixed-size array will be O(n)).

I can accept your idea (and I can see other people here seem to accept it), but 
I'd like the function to receive the array by value if the array is small, and 
by reference if it's large (small and large are defined in terms of true 
bytes). This can be done automatically by the compiler, but this looks unsafe, 
because it's bad when the compiler changes the program semantics in an 
invisible way. So something explicit is better:
void foo(bigref T[3] a)

That syntax means that if (T[3]).sizeof is big enough then it's a ref argument, 
otherwise it's a value argument.

But I think it's better to be able to somehow define that "bigref" in the 
standard library:
void foo(Bigref!T[3] a)

Andrei may like something like that. To do that "ref" may need to change its 
nature a little, becoming a kind of subtype that the user can define and use. I 
am ignorant about this, maybe T[3].REF can be the type of the reference to 
T[3], as T[3]* is the type of the pointer to a T[3]. If something like this is 
possible then that Bigref!() becomes just a template that contains a static if 
that according to the value of (T[3]).sizeof and some constant threshold value 
becomes an alias of T[3] or T[3].REF.

Questions:
1) How can I allocate a fixed-size array on the heap?
2) Can such array allocated on the heap be return by "ref" from a function? (Or 
do I have to return it just by pointer)?
3) How can I implement and use a variable-length struct like this, that 
sometimes improves the performance of some code?
struct S(T) {
  T cargo;
  int len;
  int[0];
}
(variable-length structs can even grow in both ways, and the pointer that 
points to them has to point to their middle, to a field that contains two 
lengths, but such structs are are less common, so they may be ignored in this 
discussion).
4) LLVM, the backend of LDC, can map small array operations on SSE operations, 
so it can often perform the sum among two fixed-sized arrays of integers in a 
single asm instruction ad clock cycle. I'd like D to pass such semantics to the 
backend. We can discuss this later.

Bye,
bearophile

Reply via email to