On Wednesday, 19 October 2016 at 19:19:35 UTC, Jonathan M Davis
wrote:
That's an orthogonal issue. My point is that normally, a
parameter is a ref parameter, because the function is going to
use that value and potentially mutate it in the process, and
you want the original variable that was passed in to be mutated
rather than for the function to be operating on a copy.
However, once you can pass rvalues to ref parameters, there
will likely be a sharp increase in the number of ref parameters
whose entire purpose in being ref is to avoid a copy rather
than because the original variable is supposed to be mutated.
That increases the risk of accidentally mutating function
arguments as well as making it far less obvious when a function
is supposed to be mutating its argument. C++ solved that
problem by making it so that only const ref parameters could
take rvalues, whereas we would be totally open to it if
non-const ref parameters accepted rvalues.
Whether the argument escapes the function doesn't matter for
any of that. There may be good reasons why you don't want it
to, in which case, if scope is implemented to prevent ref
parameters from escaping, scope will give you that. But just
because you want to mutate the ref argument doesn't necessarily
mean that you care about it escaping. You _do_ care if the
purpose is simply to avoid a copy, because you don't want the
rvalue to escape, since that would be an @safety issue, and so
it would make sense to require scope in that case, but at best,
that means that the lack of scope indicates that the ref
argument is supposed to be mutated as opposed to simply avoid a
copy, whereas scope ref says nothing about whether the ref
argument is supposed to be mutated or simply avoid a copy -
just that whatever the argument is, it should no escape.
Ok, I understand what you mean, but as long as the argument
cannot escape I have a different opinion.
So, arguably, it makes more sense to have a new attribute that
makes it specifically so that a ref accepts rvalues (e.g.
@rvalue ref) rather than making ref in general accept rvalues
(the new attribute could even imply scope, since it would be
required), but that would mean adding yet another attribute,
and we arguably have too many of those already.
- Jonathan M Davis
Yes, we have way to many. So it would make more sense if we add
helper/wrappers into phobos (at least for the time being) and
refer to them.
My byRef "hack" or even my last experiment below could lower the
dissatisfaction.
----
struct Vector2f
{
float x, y;
}
void one(ref const Vector2f v)
{
writeln(v.x, '|', v.y);
}
void two(ref const Vector2f source, ref const Vector2f target)
{
writefln("From (%.2f|%.2f) to (%.2f|%.2f)", source.x,
source.y, target.x, target.y);
}
void invoke(alias f, V...)(V vs)
{
f(vs);
}
void invoke(F, V...)(F f, V vs)
{
f(vs);
}
invoke!one(Vector2f(10, 20));
invoke!two(Vector2f(1, 2), Vector2f(3, 4));
invoke(&one, Vector2f(10, 20));
invoke(&two, Vector2f(1, 2), Vector2f(3, 4));
----