This may be a topic already discussed a lot in the past, if so please bear with me, it may take me years to catch most of the things already discussed.
I think the way to pass a built-in array may have few main usages: 1) read/write the array, but the length and ptr can't change (default in D1) (length and ptr can change, but only locally to the function). 2) read/write the array, generally the length can change ("ref") (ptr too can change). 3) read items and length/ptr of the array, but they can't change (doable in D2). 4) all the array is built inside the function, so this argument is just a way to have a function with multiple returns ("out"). (the record/Record struct like of my dlibs may remove the need for this in all but the most performance-critical spots of the code). The #1 (default in D1) is a common enough case, but in my code I have seen it's easy for me (in few programs, not in all of them) to modify the length too and forget to add the "ref". This has lead to small bugs, because the compiler digests this silently, and outside the function you just see the length unchanged. So I don't like the #1 to be the default. So I think I may like the #2 to be the default. I may even accept #3 to be the default, because it can't lead to bugs (when you try to change something the compiler stops the compilation, and you add something to remove the immutability). Keeping #1 as default looks a little tricky to me, because you seem able to change both the items and the pointer/length of the array, while you can only change the items. If having #2 as default isn't possible for some reason, then I may like to have a #5 as default: 5) read/write the array, but the length and ptr can't change. Length and ptr are truly immutable inside the function, so if you try to change them, the compiler raises an error at compile time. In such situation I just put a "ref" to solve the problem. This doesn't lead to bugs in my code. Bye, bearophile