On Saturday, 24 March 2018 at 11:57:25 UTC, John Colvin wrote:
I understand what you want, but I'm struggling to understand
why it's such a huge deal.
The reason you want to pass by reference is for performance, to
avoid copying the data at the call boundary.
It's pretty simple:
float foo() { ... }
ref float bar() { ... }
void someFunc(ref float);
someFunc(bar()); // ok
float temp = foo();
someFunc(temp); // Have to create a temporary anyways for the
function to work
someFunc(foo()); // Compile error, need to use the hideous code
above
So there really isn't any performance penalty cause if you want
to call that function you are going to have to create a temporary
variable anyways, but now you can't just call the function in one
line. It requires multiple lines and a temporary variable name.
This becomes especially horrible for math libraries:
void someFunc(ref Vector3) { ... }
someFunc(a + b); // Can't do this
Vector3 temp = a + b;
someFunc(temp); // Have to do this
So there's no performance penalty for what he is requesting, but
allows for a cleaner syntax to do the exact same thing.
So there are 2 cases: an lvalue needs to be passed, or an
rvalue needs to be passed.
1. The address of the lvalue is passed.
2. The rvalue is copied to a local, then the address of that
local is passed.
So in the rvalue case, you're not getting the performance
benefit of passing by reference, because you have to copy to a
local anyway.
What I would do in D currently to get the same performance and
API:
void foo(float[32] v) { foo(v); }
void foo(ref float[32] v) { ... }
or
void foo()(auto ref float[32] v) { ... }
What is so totally unacceptable about those solutions? I
personally like the second because it scales better to multiple
parameters. I know you have said it's not relevant and annoying
that people bring up auto ref, but I dont' get how or why. It's
exactly D's solution to the problem.
It doesn't scale better, that's part of the problem:
void foo()(auto ref MyType1, auto ref MyType2, auto ref MyType3,
auto ref MyType4) { ... }
The above has the possibility of generating 16 different
functions that basically all do the exact same thing. It creates
excessive bloat, and now what if you want to take the address of
the function? You can't cause you have to choose between one of
the 16 variants.
This is template bloat at it's finest, except it isn't even doing
anything useful. I can only imagine telling someone they have to
code gen 16 identical functions just to be able to call a
function without having to create useless temporary variables in
the scope a function is being called in.